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 "Package.h" 35 #include "Lock.h" 36 #include "Helpers.h" 37 #include "JavaUserPreferences.h" 38 #include "Macros.h" 39 #include "IniFile.h" 40 41 #include <assert.h> 42 43 44 Package::Package(void) { 45 FInitialized = false; 46 Initialize(); 47 } 48 49 TPlatformNumber StringToPercentageOfNumber(TString Value, TPlatformNumber Number) { 50 TPlatformNumber result = 0; 51 size_t percentage = atoi(PlatformString(Value.c_str())); 52 53 if (percentage > 0 && Number > 0) { 54 result = Number * percentage / 100; 55 } 56 57 return result; 58 } 59 60 void Package::Initialize() { 61 if (FInitialized == true) { 62 return; 63 } 64 65 Platform& platform = Platform::GetInstance(); 66 67 FBootFields = new PackageBootFields(); 68 FDebugging = dsNone; 69 70 FBootFields->FPackageRootDirectory = platform.GetPackageRootDirectory(); 71 FBootFields->FPackageAppDirectory = platform.GetPackageAppDirectory(); 72 FBootFields->FPackageLauncherDirectory = platform.GetPackageLauncherDirectory(); 73 FBootFields->FAppDataDirectory = platform.GetAppDataDirectory(); 74 75 std::map<TString, TString> keys = platform.GetKeys(); 76 77 // Read from configure.cfg/Info.plist 78 AutoFreePtr<ISectionalPropertyContainer> config = platform.GetConfigFile(platform.GetConfigFileName()); 79 80 config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[CONFIG_APP_ID_KEY], FBootFields->FAppID); 81 config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[PACKAGER_APP_DATA_DIR], FBootFields->FPackageAppDataDirectory); 82 FBootFields->FPackageAppDataDirectory = FilePath::FixPathForPlatform(FBootFields->FPackageAppDataDirectory); 83 84 // Main JAR. 85 config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[CONFIG_MAINJAR_KEY], FBootFields->FMainJar); 86 FBootFields->FMainJar = FilePath::IncludeTrailingSeparater(GetPackageAppDirectory()) + 87 FilePath::FixPathForPlatform(FBootFields->FMainJar); 88 89 // Classpath. 90 // 1. If the provided class path contains main jar then only use provided class path. 91 // 2. If class path provided by config file is empty then add main jar. 92 // 3. If main jar is not in provided class path then add it. 93 config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[CONFIG_CLASSPATH_KEY], FBootFields->FClassPath); 94 FBootFields->FClassPath = FilePath::FixPathSeparatorForPlatform(FBootFields->FClassPath); 95 96 if (FBootFields->FClassPath.empty() == true) { 97 FBootFields->FClassPath = GetMainJar(); 98 } 99 else if (FBootFields->FClassPath.find(GetMainJar()) == TString::npos) { 100 FBootFields->FClassPath = GetMainJar() + FilePath::PathSeparator() + FBootFields->FClassPath; 101 } 102 103 // Modulepath. 104 config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[CONFIG_MODULEPATH_KEY], FBootFields->FModulePath); 105 FBootFields->FModulePath = FilePath::FixPathSeparatorForPlatform(FBootFields->FModulePath); 106 107 // Main Class. 108 config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[CONFIG_MAINCLASSNAME_KEY], FBootFields->FMainClassName); 109 110 // Splash Screen. 111 if (config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[CONFIG_SPLASH_KEY], FBootFields->FSplashScreenFileName) == true) { 112 FBootFields->FSplashScreenFileName = FilePath::IncludeTrailingSeparater(GetPackageAppDirectory()) + 113 FilePath::FixPathForPlatform(FBootFields->FSplashScreenFileName); 114 115 if (FilePath::FileExists(FBootFields->FSplashScreenFileName) == false) { 116 FBootFields->FSplashScreenFileName = _T(""); 117 } 118 } 119 120 // Runtime. 121 FBootFields->FIsRuntimeBundled = true; 122 config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[JVM_RUNTIME_KEY], FBootFields->FJVMRuntimeDirectory); 123 124 if (FBootFields->FJVMRuntimeDirectory.empty()) { 125 FBootFields->FIsRuntimeBundled = false; 126 FBootFields->FJVMRuntimeDirectory = platform.GetSystemJRE(); 127 } 128 129 // Read jvmargs. 130 PromoteAppCDSState(config); 131 ReadJVMArgs(config); 132 133 // Read args if none were passed in. 134 if (FBootFields->FArgs.size() == 0) { 135 OrderedMap<TString, TString> args; 136 137 if (config->GetSection(keys[CONFIG_SECTION_ARGOPTIONS], args) == true) { 138 FBootFields->FArgs = Helpers::MapToNameValueList(args); 139 } 140 } 141 142 // Read jvmuserarg defaults. 143 config->GetSection(keys[CONFIG_SECTION_JVMUSEROPTIONS], FDefaultJVMUserArgs); 144 145 // Load JVM user overrides. 146 TString jvmUserArgsConfigFileName = GetJVMUserArgsConfigFileName(); 147 148 if (FilePath::FileExists(jvmUserArgsConfigFileName) == true) { 149 // Load new location for user VM overrides. 150 IniFile userConfig; 151 152 if (userConfig.LoadFromFile(jvmUserArgsConfigFileName) == false) { 153 // New property file format was not found, attempt to load old property file format. 154 userConfig.GetSection(keys[CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS], FJVMUserArgsOverrides); 155 } 156 157 userConfig.GetSection(keys[CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS], FJVMUserArgsOverrides); 158 } 159 else { 160 // Attemp to load java.util.prefs for legacy JVM user overrides. 161 AutoFreePtr<JavaUserPreferences> javaPreferences(JavaUserPreferences::CreateInstance()); 162 163 if (javaPreferences->Load(GetAppID()) == true) { 164 FJVMUserArgsOverrides = javaPreferences->GetData(); 165 } 166 } 167 168 // Auto Memory. 169 TString autoMemory; 170 171 if (config->GetValue(keys[CONFIG_SECTION_APPLICATION], keys[CONFIG_APP_MEMORY], autoMemory) == true) { 172 if (autoMemory == _T("auto") || autoMemory == _T("100%")) { 173 FBootFields->FMemoryState = PackageBootFields::msAuto; 174 FBootFields->FMemorySize = platform.GetMemorySize(); 175 } 176 else if (autoMemory.length() == 2 && isdigit(autoMemory[0]) && autoMemory[1] == '%') { 177 FBootFields->FMemoryState = PackageBootFields::msAuto; 178 FBootFields->FMemorySize = StringToPercentageOfNumber(autoMemory.substr(0, 1), platform.GetMemorySize()); 179 } 180 else if (autoMemory.length() == 3 && isdigit(autoMemory[0]) && isdigit(autoMemory[1]) && autoMemory[2] == '%') { 181 FBootFields->FMemoryState = PackageBootFields::msAuto; 182 FBootFields->FMemorySize = StringToPercentageOfNumber(autoMemory.substr(0, 2), platform.GetMemorySize()); 183 } 184 else { 185 FBootFields->FMemoryState = PackageBootFields::msManual; 186 FBootFields->FMemorySize = 0; 187 } 188 } 189 190 MergeJVMDefaultsWithOverrides(); 191 } 192 193 void Package::Clear() { 194 FreeBootFields(); 195 FJVMUserArgsOverrides.Clear(); 196 FDefaultJVMUserArgs.Clear(); 197 FJVMUserArgs.Clear(); 198 FInitialized = false; 199 } 200 201 // This is the only location that the AppCDS state should be modified except 202 // by command line arguments provided by the user. 203 // 204 // The state of AppCDS is as follows: 205 // 206 // -> cdsUninitialized 207 // -> cdsGenCache If -Xappcds:generatecache 208 // -> cdsDisabled If -Xappcds:off 209 // -> cdsEnabled If "AppCDSJVMOptions" section is present 210 // -> cdsAuto If "AppCDSJVMOptions" section is present and app.appcds.cache=auto 211 // -> cdsDisabled Default 212 // 213 void Package::PromoteAppCDSState(ISectionalPropertyContainer* Config) { 214 Platform& platform = Platform::GetInstance(); 215 std::map<TString, TString> keys = platform.GetKeys(); 216 217 // The AppCDS state can change at this point. 218 switch (platform.GetAppCDSState()) { 219 case cdsEnabled: 220 case cdsAuto: 221 case cdsDisabled: 222 case cdsGenCache: { 223 // Do nothing. 224 break; 225 } 226 227 case cdsUninitialized: { 228 if (Config->ContainsSection(keys[CONFIG_SECTION_APPCDSJVMOPTIONS]) == true) { 229 // If the AppCDS section is present then enable AppCDS. 230 TString appCDSCacheValue; 231 232 // If running with AppCDS enabled, and the configuration has been setup so "auto" is enabled, then 233 // the launcher will attempt to generate the cache file automatically and run the application. 234 if (Config->GetValue(keys[CONFIG_SECTION_APPLICATION], _T("app.appcds.cache"), appCDSCacheValue) == true && 235 appCDSCacheValue == _T("auto")) { 236 platform.SetAppCDSState(cdsAuto); 237 } 238 else { 239 platform.SetAppCDSState(cdsEnabled); 240 } 241 } 242 else { 243 244 platform.SetAppCDSState(cdsDisabled); 245 } 246 } 247 } 248 } 249 250 void Package::ReadJVMArgs(ISectionalPropertyContainer* Config) { 251 Platform& platform = Platform::GetInstance(); 252 std::map<TString, TString> keys = platform.GetKeys(); 253 254 // Evaluate based on the current AppCDS state. 255 switch (platform.GetAppCDSState()) { 256 case cdsUninitialized: { 257 throw Exception(_T("Internal Error")); 258 } 259 260 case cdsDisabled: { 261 Config->GetSection(keys[CONFIG_SECTION_JVMOPTIONS], FBootFields->FJVMArgs); 262 break; 263 } 264 265 case cdsGenCache: { 266 Config->GetSection(keys[CONFIG_SECTION_APPCDSGENERATECACHEJVMOPTIONS], FBootFields->FJVMArgs); 267 break; 268 } 269 270 case cdsAuto: 271 case cdsEnabled: { 272 if (Config->GetValue(keys[CONFIG_SECTION_APPCDSJVMOPTIONS], 273 _T( "-XX:SharedArchiveFile"), FBootFields->FAppCDSCacheFileName) == true) { 274 // File names may contain the incorrect path separators. The cache file name must be 275 // corrected at this point. 276 if (FBootFields->FAppCDSCacheFileName.empty() == false) { 277 IniFile* iniConfig = dynamic_cast<IniFile*>(Config); 278 279 if (iniConfig != NULL) { 280 FBootFields->FAppCDSCacheFileName = FilePath::FixPathForPlatform(FBootFields->FAppCDSCacheFileName); 281 iniConfig->SetValue(keys[CONFIG_SECTION_APPCDSJVMOPTIONS], 282 _T( "-XX:SharedArchiveFile"), FBootFields->FAppCDSCacheFileName); 283 } 284 } 285 286 Config->GetSection(keys[CONFIG_SECTION_APPCDSJVMOPTIONS], FBootFields->FJVMArgs); 287 } 288 289 break; 290 } 291 } 292 } 293 294 void Package::SetCommandLineArguments(int argc, TCHAR* argv[]) { 295 if (argc > 0) { 296 std::list<TString> args; 297 298 // Prepare app arguments. Skip value at index 0 - this is path to executable. 299 FBootFields->FCommandName = argv[0]; 300 301 // Path to executable is at 0 index so start at index 1. 302 for (int index = 1; index < argc; index++) { 303 TString arg = argv[index]; 304 305 #ifdef DEBUG 306 if (arg == _T("-debug")) { 307 FDebugging = dsNative; 308 } 309 310 if (arg == _T("-javadebug")) { 311 FDebugging = dsJava; 312 } 313 #endif //DEBUG 314 #ifdef MAC 315 if (arg.find(_T("-psn_"), 0) != TString::npos) { 316 Platform& platform = Platform::GetInstance(); 317 318 if (platform.IsMainThread() == true) { 319 #ifdef DEBUG 320 printf("%s\n", arg.c_str()); 321 #endif //DEBUG 322 continue; 323 } 324 } 325 326 if (arg == _T("-NSDocumentRevisionsDebugMode")) { 327 // Ignore -NSDocumentRevisionsDebugMode and the following YES/NO 328 index++; 329 continue; 330 } 331 #endif //MAC 332 333 args.push_back(arg); 334 } 335 336 if (args.size() > 0) { 337 FBootFields->FArgs = args; 338 } 339 } 340 } 341 342 Package& Package::GetInstance() { 343 static Package instance; // Guaranteed to be destroyed. Instantiated on first use. 344 return instance; 345 } 346 347 Package::~Package(void) { 348 FreeBootFields(); 349 } 350 351 void Package::FreeBootFields() { 352 if (FBootFields != NULL) { 353 delete FBootFields; 354 FBootFields = NULL; 355 } 356 } 357 358 OrderedMap<TString, TString> Package::GetJVMArgs() { 359 return FBootFields->FJVMArgs; 360 } 361 362 OrderedMap<TString, TString> Package::GetDefaultJVMUserArgs() { 363 return FDefaultJVMUserArgs; 364 } 365 366 OrderedMap<TString, TString> Package::GetJVMUserArgOverrides() { 367 return FJVMUserArgsOverrides; 368 } 369 370 std::vector<TString> GetKeysThatAreNotDuplicates(OrderedMap<TString, TString> &Defaults, 371 OrderedMap<TString, TString> &Overrides) { 372 std::vector<TString> result; 373 std::vector<TString> overrideKeys = Overrides.GetKeys(); 374 375 for (size_t index = 0; index < overrideKeys.size(); index++) { 376 TString overridesKey = overrideKeys[index]; 377 TString overridesValue; 378 TString defaultValue; 379 380 if ((Defaults.ContainsKey(overridesKey) == false) || 381 (Defaults.GetValue(overridesKey, defaultValue) == true && 382 Overrides.GetValue(overridesKey, overridesValue) == true && 383 defaultValue != overridesValue)) { 384 result.push_back(overridesKey); 385 } 386 } 387 388 return result; 389 } 390 391 OrderedMap<TString, TString> CreateOrderedMapFromKeyList(OrderedMap<TString, TString> &Map, 392 std::vector<TString> &Keys) { 393 OrderedMap<TString, TString> result; 394 395 for (size_t index = 0; index < Keys.size(); index++) { 396 TString key = Keys[index]; 397 TString value; 398 399 if (Map.GetValue(key, value) == true) { 400 result.Append(key, value); 401 } 402 } 403 404 return result; 405 } 406 407 void Package::SetJVMUserArgOverrides(OrderedMap<TString, TString> Value) { 408 OrderedMap<TString, TString> defaults = GetDefaultJVMUserArgs(); 409 OrderedMap<TString, TString> overrides = Value; 410 411 // 1. Remove entries in the overrides that are the same as the defaults. 412 std::vector<TString> overrideKeys = GetKeysThatAreNotDuplicates(defaults, overrides); 413 414 // 2. Create an ordered map from the overrides that weren't removed. 415 FJVMUserArgsOverrides = CreateOrderedMapFromKeyList(overrides, overrideKeys); 416 417 // 3. Overwrite JVM user config overrides with provided key/value pair. 418 SaveJVMUserArgOverrides(FJVMUserArgsOverrides); 419 420 // 4. Merge defaults and overrides to produce FJVMUserArgs. 421 MergeJVMDefaultsWithOverrides(); 422 } 423 424 void Package::SaveJVMUserArgOverrides(OrderedMap<TString, TString> Data) { 425 IniFile userConfig; 426 Platform& platform = Platform::GetInstance(); 427 std::map<TString, TString> keys = platform.GetKeys(); 428 userConfig.AppendSection(keys[CONFIG_SECTION_JVMUSEROVERRIDESOPTIONS], Data); 429 userConfig.SaveToFile(GetJVMUserArgsConfigFileName()); 430 } 431 432 OrderedMap<TString, TString> Package::GetJVMUserArgs() { 433 return FJVMUserArgs; 434 } 435 436 std::vector<TString> GetKeysThatAreNotOverridesOfDefaultValues(OrderedMap<TString, TString> &Defaults, 437 OrderedMap<TString, TString> &Overrides) { 438 std::vector<TString> result; 439 std::vector<TString> keys = Overrides.GetKeys(); 440 441 for (unsigned int index = 0; index< keys.size(); index++) { 442 TString key = keys[index]; 443 444 if (Defaults.ContainsKey(key) == true) { 445 try { 446 TString value = Overrides[key]; 447 Defaults[key] = value; 448 } 449 catch (std::out_of_range) { 450 } 451 } 452 else { 453 result.push_back(key); 454 } 455 } 456 457 return result; 458 } 459 460 void Package::MergeJVMDefaultsWithOverrides() { 461 // Merge jvmuserarg defaults and jvmuserarg overrides to populate FJVMUserArgs. 462 // 1. If the key is in the config file and not the java.user.preferences the default value is used, 463 // the one from the config file. 464 // 2. If the key is in the java.user.preferences then the value from the java.user.preferences is used and 465 // the config file value is ignored. 466 // 3. If the key is not in the config file but it is in the java.user.preferences then it is added anyway. 467 // And if it is removed it won't show back up. 468 FJVMUserArgs.Clear(); 469 FJVMUserArgs.Append(FDefaultJVMUserArgs); 470 471 OrderedMap<TString, TString> overrides = GetJVMUserArgOverrides(); 472 473 // 1. Iterate over all elements in overrides to see if any items 474 // override a default value. 475 std::vector<TString> keys = GetKeysThatAreNotOverridesOfDefaultValues(FJVMUserArgs, overrides); 476 477 478 // 2. All remaining items in overrides are appended to the end. 479 for (unsigned int index = 0; index< keys.size(); index++) { 480 TString key = keys[index]; 481 TString value; 482 483 if (overrides.GetValue(key, value) == true) { 484 FJVMUserArgs.Append(key, value); 485 } 486 } 487 } 488 489 std::list<TString> Package::GetArgs() { 490 assert(FBootFields != NULL); 491 return FBootFields->FArgs; 492 } 493 494 TString Package::GetPackageRootDirectory() { 495 assert(FBootFields != NULL); 496 return FBootFields->FPackageRootDirectory; 497 } 498 499 TString Package::GetPackageAppDirectory() { 500 assert(FBootFields != NULL); 501 return FBootFields->FPackageAppDirectory; 502 } 503 504 TString Package::GetPackageLauncherDirectory() { 505 assert(FBootFields != NULL); 506 return FBootFields->FPackageLauncherDirectory; 507 } 508 509 TString Package::GetAppDataDirectory() { 510 assert(FBootFields != NULL); 511 return FBootFields->FAppDataDirectory; 512 } 513 514 TString Package::GetJVMUserArgsConfigFileName() { 515 if (FJVMUserArgsConfigFileName.empty()) { 516 Platform& platform = Platform::GetInstance(); 517 518 FJVMUserArgsConfigFileName = FilePath::IncludeTrailingSeparater(platform.GetAppDataDirectory()) + 519 FilePath::IncludeTrailingSeparater(GetPackageAppDataDirectory()) + 520 FilePath::IncludeTrailingSeparater(_T("packager")) + 521 _T("jvmuserargs.cfg"); 522 } 523 524 return FJVMUserArgsConfigFileName; 525 } 526 527 TString Package::GetAppCDSCacheDirectory() { 528 if (FAppCDSCacheDirectory.empty()) { 529 Platform& platform = Platform::GetInstance(); 530 FAppCDSCacheDirectory = FilePath::IncludeTrailingSeparater(platform.GetAppDataDirectory()) + 531 FilePath::IncludeTrailingSeparater(GetPackageAppDataDirectory()) + 532 _T("cache"); 533 534 Macros& macros = Macros::GetInstance(); 535 FAppCDSCacheDirectory = macros.ExpandMacros(FAppCDSCacheDirectory); 536 FAppCDSCacheDirectory = FilePath::FixPathForPlatform(FAppCDSCacheDirectory); 537 } 538 539 return FAppCDSCacheDirectory; 540 } 541 542 TString Package::GetAppCDSCacheFileName() { 543 assert(FBootFields != NULL); 544 545 if (FBootFields->FAppCDSCacheFileName.empty() == false) { 546 Macros& macros = Macros::GetInstance(); 547 FBootFields->FAppCDSCacheFileName = macros.ExpandMacros(FBootFields->FAppCDSCacheFileName); 548 FBootFields->FAppCDSCacheFileName = FilePath::FixPathForPlatform(FBootFields->FAppCDSCacheFileName); 549 } 550 551 return FBootFields->FAppCDSCacheFileName; 552 } 553 554 TString Package::GetAppID() { 555 assert(FBootFields != NULL); 556 return FBootFields->FAppID; 557 } 558 559 TString Package::GetPackageAppDataDirectory() { 560 assert(FBootFields != NULL); 561 return FBootFields->FPackageAppDataDirectory; 562 } 563 564 TString Package::GetClassPath() { 565 assert(FBootFields != NULL); 566 return FBootFields->FClassPath; 567 } 568 569 TString Package::GetModulePath() { 570 assert(FBootFields != NULL); 571 return FBootFields->FModulePath; 572 } 573 574 TString Package::GetMainJar() { 575 assert(FBootFields != NULL); 576 return FBootFields->FMainJar; 577 } 578 579 TString Package::GetMainClassName() { 580 assert(FBootFields != NULL); 581 return FBootFields->FMainClassName; 582 } 583 584 bool Package::IsRuntimeBundled() { 585 assert(FBootFields != NULL); 586 return FBootFields->FIsRuntimeBundled; 587 } 588 589 TString Package::GetJVMLibraryFileName() { 590 assert(FBootFields != NULL); 591 592 if (FBootFields->FJVMLibraryFileName.empty() == true) { 593 Platform& platform = Platform::GetInstance(); 594 if (IsRuntimeBundled() == true) { 595 Macros& macros = Macros::GetInstance(); 596 TString jvmRuntimePath = macros.ExpandMacros(GetJVMRuntimeDirectory()); 597 FBootFields->FJVMLibraryFileName = platform.GetBundledJVMLibraryFileName(jvmRuntimePath); 598 } 599 else { 600 FBootFields->FJVMLibraryFileName = platform.GetSystemJVMLibraryFileName(); 601 } 602 } 603 604 return FBootFields->FJVMLibraryFileName; 605 } 606 607 TString Package::GetJVMRuntimeDirectory() { 608 assert(FBootFields != NULL); 609 return FBootFields->FJVMRuntimeDirectory; 610 } 611 612 TString Package::GetSplashScreenFileName() { 613 assert(FBootFields != NULL); 614 return FBootFields->FSplashScreenFileName; 615 } 616 617 bool Package::HasSplashScreen() { 618 assert(FBootFields != NULL); 619 return FilePath::FileExists(FBootFields->FSplashScreenFileName); 620 } 621 622 TString Package::GetCommandName() { 623 assert(FBootFields != NULL); 624 return FBootFields->FCommandName; 625 } 626 627 TPlatformNumber Package::GetMemorySize() { 628 assert(FBootFields != NULL); 629 return FBootFields->FMemorySize; 630 } 631 632 PackageBootFields::MemoryState Package::GetMemoryState() { 633 assert(FBootFields != NULL); 634 return FBootFields->FMemoryState; 635 } 636 637 DebugState Package::Debugging() { 638 return FDebugging; 639 }