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