src/jdk.incubator.jpackage/share/native/libapplauncher/Package.cpp
branchJDK-8200758-branch
changeset 58994 b09ba68c6a19
parent 57455 f1290ca0fee6
equal deleted inserted replaced
58993:b5e1baa9d2c3 58994:b09ba68c6a19
       
     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 "Package.h"
       
    27 #include "Helpers.h"
       
    28 #include "Macros.h"
       
    29 #include "IniFile.h"
       
    30 
       
    31 #include <assert.h>
       
    32 
       
    33 
       
    34 Package::Package(void) {
       
    35     FInitialized = false;
       
    36     Initialize();
       
    37 }
       
    38 
       
    39 TPlatformNumber StringToPercentageOfNumber(TString Value,
       
    40         TPlatformNumber Number) {
       
    41     TPlatformNumber result = 0;
       
    42     size_t percentage = atoi(PlatformString(Value.c_str()));
       
    43 
       
    44     if (percentage > 0 && Number > 0) {
       
    45         result = Number * percentage / 100;
       
    46     }
       
    47 
       
    48     return result;
       
    49 }
       
    50 
       
    51 void Package::Initialize() {
       
    52     if (FInitialized == true) {
       
    53         return;
       
    54     }
       
    55 
       
    56     Platform& platform = Platform::GetInstance();
       
    57 
       
    58     FBootFields = new PackageBootFields();
       
    59     FDebugging = dsNone;
       
    60 
       
    61     // Allow duplicates for Java options, so we can have multiple --add-exports
       
    62     // or similar args.
       
    63     FBootFields->FJavaOptions.SetAllowDuplicates(true);
       
    64     FBootFields->FPackageRootDirectory = platform.GetPackageRootDirectory();
       
    65     FBootFields->FPackageAppDirectory = platform.GetPackageAppDirectory();
       
    66     FBootFields->FPackageLauncherDirectory =
       
    67             platform.GetPackageLauncherDirectory();
       
    68     FBootFields->FAppDataDirectory = platform.GetAppDataDirectory();
       
    69 
       
    70     std::map<TString, TString> keys = platform.GetKeys();
       
    71 
       
    72     // Read from configure.cfg/Info.plist
       
    73     AutoFreePtr<ISectionalPropertyContainer> config =
       
    74             platform.GetConfigFile(platform.GetConfigFileName());
       
    75 
       
    76     config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
    77             keys[JPACKAGE_APP_DATA_DIR], FBootFields->FPackageAppDataDirectory);
       
    78     FBootFields->FPackageAppDataDirectory =
       
    79             FilePath::FixPathForPlatform(FBootFields->FPackageAppDataDirectory);
       
    80 
       
    81     // Main JAR.
       
    82     config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
    83             keys[CONFIG_MAINJAR_KEY], FBootFields->FMainJar);
       
    84     FBootFields->FMainJar = FilePath::FixPathForPlatform(FBootFields->FMainJar);
       
    85 
       
    86     // Main Module.
       
    87     config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
    88             keys[CONFIG_MAINMODULE_KEY], FBootFields->FMainModule);
       
    89 
       
    90     // Classpath.
       
    91     // 1. If the provided class path contains main jar then only use
       
    92     //    provided class path.
       
    93     // 2. If class path provided by config file is empty then add main jar.
       
    94     // 3. If main jar is not in provided class path then add it.
       
    95     config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
    96             keys[CONFIG_CLASSPATH_KEY], FBootFields->FClassPath);
       
    97     FBootFields->FClassPath =
       
    98             FilePath::FixPathSeparatorForPlatform(FBootFields->FClassPath);
       
    99 
       
   100     if (FBootFields->FClassPath.empty() == true) {
       
   101         FBootFields->FClassPath = GetMainJar();
       
   102     } else if (FBootFields->FClassPath.find(GetMainJar()) == TString::npos) {
       
   103         FBootFields->FClassPath = GetMainJar()
       
   104                 + FilePath::PathSeparator() + FBootFields->FClassPath;
       
   105     }
       
   106 
       
   107     // Modulepath.
       
   108     config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
   109             keys[CONFIG_MODULEPATH_KEY], FBootFields->FModulePath);
       
   110     FBootFields->FModulePath =
       
   111             FilePath::FixPathSeparatorForPlatform(FBootFields->FModulePath);
       
   112 
       
   113     // Main Class.
       
   114     config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
   115             keys[CONFIG_MAINCLASSNAME_KEY], FBootFields->FMainClassName);
       
   116 
       
   117     // Splash Screen.
       
   118     if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
   119             keys[CONFIG_SPLASH_KEY],
       
   120             FBootFields->FSplashScreenFileName) == true) {
       
   121         FBootFields->FSplashScreenFileName =
       
   122             FilePath::IncludeTrailingSeparator(GetPackageAppDirectory())
       
   123             + FilePath::FixPathForPlatform(FBootFields->FSplashScreenFileName);
       
   124 
       
   125         if (FilePath::FileExists(FBootFields->FSplashScreenFileName) == false) {
       
   126             FBootFields->FSplashScreenFileName = _T("");
       
   127         }
       
   128     }
       
   129 
       
   130     // Runtime.
       
   131     config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
   132             keys[JAVA_RUNTIME_KEY], FBootFields->FJavaRuntimeDirectory);
       
   133 
       
   134     // Read jvmargs.
       
   135     PromoteAppCDSState(config);
       
   136     ReadJavaOptions(config);
       
   137 
       
   138     // Read args if none were passed in.
       
   139     if (FBootFields->FArgs.size() == 0) {
       
   140         OrderedMap<TString, TString> args;
       
   141 
       
   142         if (config->GetSection(keys[CONFIG_SECTION_ARGOPTIONS], args) == true) {
       
   143             FBootFields->FArgs = Helpers::MapToNameValueList(args);
       
   144         }
       
   145     }
       
   146 
       
   147     // Auto Memory.
       
   148     TString autoMemory;
       
   149 
       
   150     if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
   151             keys[CONFIG_APP_MEMORY], autoMemory) == true) {
       
   152         if (autoMemory == _T("auto") || autoMemory == _T("100%")) {
       
   153             FBootFields->FMemoryState = PackageBootFields::msAuto;
       
   154             FBootFields->FMemorySize = platform.GetMemorySize();
       
   155         } else if (autoMemory.length() == 2 && isdigit(autoMemory[0]) &&
       
   156                 autoMemory[1] == '%') {
       
   157             FBootFields->FMemoryState = PackageBootFields::msAuto;
       
   158             FBootFields->FMemorySize =
       
   159                     StringToPercentageOfNumber(autoMemory.substr(0, 1),
       
   160                     platform.GetMemorySize());
       
   161         } else if (autoMemory.length() == 3 && isdigit(autoMemory[0]) &&
       
   162                 isdigit(autoMemory[1]) && autoMemory[2] == '%') {
       
   163             FBootFields->FMemoryState = PackageBootFields::msAuto;
       
   164             FBootFields->FMemorySize =
       
   165                     StringToPercentageOfNumber(autoMemory.substr(0, 2),
       
   166                     platform.GetMemorySize());
       
   167         } else {
       
   168             FBootFields->FMemoryState = PackageBootFields::msManual;
       
   169             FBootFields->FMemorySize = 0;
       
   170         }
       
   171     }
       
   172 
       
   173     // Debug
       
   174     TString debug;
       
   175     if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
   176             keys[CONFIG_APP_DEBUG], debug) == true) {
       
   177         FBootFields->FArgs.push_back(debug);
       
   178     }
       
   179 }
       
   180 
       
   181 void Package::Clear() {
       
   182     FreeBootFields();
       
   183     FInitialized = false;
       
   184 }
       
   185 
       
   186 // This is the only location that the AppCDS state should be modified except
       
   187 // by command line arguments provided by the user.
       
   188 //
       
   189 // The state of AppCDS is as follows:
       
   190 //
       
   191 // -> cdsUninitialized
       
   192 //    -> cdsGenCache If -Xappcds:generatecache
       
   193 //    -> cdsDisabled If -Xappcds:off
       
   194 //    -> cdsEnabled If "AppCDSJavaOptions" section is present
       
   195 //    -> cdsAuto If "AppCDSJavaOptions" section is present and
       
   196 //               app.appcds.cache=auto
       
   197 //    -> cdsDisabled Default
       
   198 //
       
   199 void Package::PromoteAppCDSState(ISectionalPropertyContainer* Config) {
       
   200     Platform& platform = Platform::GetInstance();
       
   201     std::map<TString, TString> keys = platform.GetKeys();
       
   202 
       
   203     // The AppCDS state can change at this point.
       
   204     switch (platform.GetAppCDSState()) {
       
   205         case cdsEnabled:
       
   206         case cdsAuto:
       
   207         case cdsDisabled:
       
   208         case cdsGenCache: {
       
   209             // Do nothing.
       
   210             break;
       
   211         }
       
   212 
       
   213         case cdsUninitialized: {
       
   214             if (Config->ContainsSection(
       
   215                     keys[CONFIG_SECTION_APPCDSJAVAOPTIONS]) == true) {
       
   216                 // If the AppCDS section is present then enable AppCDS.
       
   217                 TString appCDSCacheValue;
       
   218 
       
   219                 // If running with AppCDS enabled, and the configuration has
       
   220                 // been setup so "auto" is enabled, then
       
   221                 // the launcher will attempt to generate the cache file
       
   222                 // automatically and run the application.
       
   223                 if (Config->GetValue(keys[CONFIG_SECTION_APPLICATION],
       
   224                         _T("app.appcds.cache"), appCDSCacheValue) == true &&
       
   225                     appCDSCacheValue == _T("auto")) {
       
   226                     platform.SetAppCDSState(cdsAuto);
       
   227                 }
       
   228                 else {
       
   229                     platform.SetAppCDSState(cdsEnabled);
       
   230                 }
       
   231             } else {
       
   232 
       
   233                 platform.SetAppCDSState(cdsDisabled);
       
   234             }
       
   235         }
       
   236     }
       
   237 }
       
   238 
       
   239 void Package::ReadJavaOptions(ISectionalPropertyContainer* Config) {
       
   240     Platform& platform = Platform::GetInstance();
       
   241     std::map<TString, TString> keys = platform.GetKeys();
       
   242 
       
   243     // Evaluate based on the current AppCDS state.
       
   244     switch (platform.GetAppCDSState()) {
       
   245         case cdsUninitialized: {
       
   246             throw Exception(_T("Internal Error"));
       
   247         }
       
   248 
       
   249         case cdsDisabled: {
       
   250             Config->GetSection(keys[CONFIG_SECTION_JAVAOPTIONS],
       
   251                     FBootFields->FJavaOptions);
       
   252             break;
       
   253         }
       
   254 
       
   255         case cdsGenCache: {
       
   256             Config->GetSection(keys[
       
   257                     CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS],
       
   258                     FBootFields->FJavaOptions);
       
   259             break;
       
   260         }
       
   261 
       
   262         case cdsAuto:
       
   263         case cdsEnabled: {
       
   264             if (Config->GetValue(keys[CONFIG_SECTION_APPCDSJAVAOPTIONS],
       
   265                     _T( "-XX:SharedArchiveFile"),
       
   266                     FBootFields->FAppCDSCacheFileName) == true) {
       
   267                 // File names may contain the incorrect path separators.
       
   268                 // The cache file name must be corrected at this point.
       
   269                 if (FBootFields->FAppCDSCacheFileName.empty() == false) {
       
   270                     IniFile* iniConfig = dynamic_cast<IniFile*>(Config);
       
   271 
       
   272                     if (iniConfig != NULL) {
       
   273                         FBootFields->FAppCDSCacheFileName =
       
   274                                 FilePath::FixPathForPlatform(
       
   275                                 FBootFields->FAppCDSCacheFileName);
       
   276                         iniConfig->SetValue(keys[
       
   277                                 CONFIG_SECTION_APPCDSJAVAOPTIONS],
       
   278                                 _T( "-XX:SharedArchiveFile"),
       
   279                                 FBootFields->FAppCDSCacheFileName);
       
   280                     }
       
   281                 }
       
   282 
       
   283                 Config->GetSection(keys[CONFIG_SECTION_APPCDSJAVAOPTIONS],
       
   284                         FBootFields->FJavaOptions);
       
   285             }
       
   286 
       
   287             break;
       
   288         }
       
   289     }
       
   290 }
       
   291 
       
   292 void Package::SetCommandLineArguments(int argc, TCHAR* argv[]) {
       
   293     if (argc > 0) {
       
   294         std::list<TString> args;
       
   295 
       
   296         // Prepare app arguments. Skip value at index 0 -
       
   297         // this is path to executable.
       
   298         FBootFields->FCommandName = argv[0];
       
   299 
       
   300         // Path to executable is at 0 index so start at index 1.
       
   301         for (int index = 1; index < argc; index++) {
       
   302             TString arg = argv[index];
       
   303 
       
   304 #ifdef DEBUG
       
   305             if (arg == _T("-debug")) {
       
   306                 FDebugging = dsNative;
       
   307             }
       
   308 
       
   309             if (arg == _T("-javadebug")) {
       
   310                 FDebugging = dsJava;
       
   311             }
       
   312 #endif //DEBUG
       
   313 #ifdef MAC
       
   314             if (arg.find(_T("-psn_"), 0) != TString::npos) {
       
   315                 Platform& platform = Platform::GetInstance();
       
   316 
       
   317                 if (platform.IsMainThread() == true) {
       
   318 #ifdef DEBUG
       
   319                     printf("%s\n", arg.c_str());
       
   320 #endif //DEBUG
       
   321                     continue;
       
   322                 }
       
   323             }
       
   324 
       
   325             if (arg == _T("-NSDocumentRevisionsDebugMode")) {
       
   326                 // Ignore -NSDocumentRevisionsDebugMode and
       
   327                 // 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;
       
   344     // Guaranteed to be destroyed. Instantiated on first use.
       
   345     return instance;
       
   346 }
       
   347 
       
   348 Package::~Package(void) {
       
   349     FreeBootFields();
       
   350 }
       
   351 
       
   352 void Package::FreeBootFields() {
       
   353     if (FBootFields != NULL) {
       
   354         delete FBootFields;
       
   355         FBootFields = NULL;
       
   356     }
       
   357 }
       
   358 
       
   359 OrderedMap<TString, TString> Package::GetJavaOptions() {
       
   360     return FBootFields->FJavaOptions;
       
   361 }
       
   362 
       
   363 std::vector<TString> GetKeysThatAreNotDuplicates(OrderedMap<TString,
       
   364         TString> &Defaults, OrderedMap<TString, TString> &Overrides) {
       
   365     std::vector<TString> result;
       
   366     std::vector<TString> overrideKeys = Overrides.GetKeys();
       
   367 
       
   368     for (size_t index = 0; index < overrideKeys.size(); index++) {
       
   369         TString overridesKey = overrideKeys[index];
       
   370         TString overridesValue;
       
   371         TString defaultValue;
       
   372 
       
   373         if ((Defaults.ContainsKey(overridesKey) == false) ||
       
   374            (Defaults.GetValue(overridesKey, defaultValue) == true &&
       
   375             Overrides.GetValue(overridesKey, overridesValue) == true &&
       
   376             defaultValue != overridesValue)) {
       
   377             result.push_back(overridesKey);
       
   378         }
       
   379     }
       
   380 
       
   381     return result;
       
   382 }
       
   383 
       
   384 OrderedMap<TString, TString> CreateOrderedMapFromKeyList(OrderedMap<TString,
       
   385         TString> &Map, std::vector<TString> &Keys) {
       
   386     OrderedMap<TString, TString> result;
       
   387 
       
   388     for (size_t index = 0; index < Keys.size(); index++) {
       
   389         TString key = Keys[index];
       
   390         TString value;
       
   391 
       
   392         if (Map.GetValue(key, value) == true) {
       
   393             result.Append(key, value);
       
   394         }
       
   395     }
       
   396 
       
   397     return result;
       
   398 }
       
   399 
       
   400 std::vector<TString> GetKeysThatAreNotOverridesOfDefaultValues(
       
   401         OrderedMap<TString, TString> &Defaults, OrderedMap<TString,
       
   402         TString> &Overrides) {
       
   403     std::vector<TString> result;
       
   404     std::vector<TString> keys = Overrides.GetKeys();
       
   405 
       
   406     for (unsigned int index = 0; index< keys.size(); index++) {
       
   407         TString key = keys[index];
       
   408 
       
   409         if (Defaults.ContainsKey(key) == true) {
       
   410             try {
       
   411                 TString value = Overrides[key];
       
   412                 Defaults[key] = value;
       
   413             }
       
   414             catch (std::out_of_range &) {
       
   415             }
       
   416         }
       
   417         else {
       
   418             result.push_back(key);
       
   419         }
       
   420     }
       
   421 
       
   422     return result;
       
   423 }
       
   424 
       
   425 std::list<TString> Package::GetArgs() {
       
   426     assert(FBootFields != NULL);
       
   427     return FBootFields->FArgs;
       
   428 }
       
   429 
       
   430 TString Package::GetPackageRootDirectory() {
       
   431     assert(FBootFields != NULL);
       
   432     return FBootFields->FPackageRootDirectory;
       
   433 }
       
   434 
       
   435 TString Package::GetPackageAppDirectory() {
       
   436     assert(FBootFields != NULL);
       
   437     return FBootFields->FPackageAppDirectory;
       
   438 }
       
   439 
       
   440 TString Package::GetPackageLauncherDirectory() {
       
   441     assert(FBootFields != NULL);
       
   442     return FBootFields->FPackageLauncherDirectory;
       
   443 }
       
   444 
       
   445 TString Package::GetAppDataDirectory() {
       
   446     assert(FBootFields != NULL);
       
   447     return FBootFields->FAppDataDirectory;
       
   448 }
       
   449 
       
   450 TString Package::GetAppCDSCacheDirectory() {
       
   451     if (FAppCDSCacheDirectory.empty()) {
       
   452         Platform& platform = Platform::GetInstance();
       
   453         FAppCDSCacheDirectory = FilePath::IncludeTrailingSeparator(
       
   454                 platform.GetAppDataDirectory())
       
   455                 + FilePath::IncludeTrailingSeparator(
       
   456                 GetPackageAppDataDirectory()) + _T("cache");
       
   457 
       
   458         Macros& macros = Macros::GetInstance();
       
   459         FAppCDSCacheDirectory = macros.ExpandMacros(FAppCDSCacheDirectory);
       
   460         FAppCDSCacheDirectory =
       
   461                 FilePath::FixPathForPlatform(FAppCDSCacheDirectory);
       
   462     }
       
   463 
       
   464     return FAppCDSCacheDirectory;
       
   465 }
       
   466 
       
   467 TString Package::GetAppCDSCacheFileName() {
       
   468     assert(FBootFields != NULL);
       
   469 
       
   470     if (FBootFields->FAppCDSCacheFileName.empty() == false) {
       
   471         Macros& macros = Macros::GetInstance();
       
   472         FBootFields->FAppCDSCacheFileName =
       
   473                 macros.ExpandMacros(FBootFields->FAppCDSCacheFileName);
       
   474         FBootFields->FAppCDSCacheFileName =
       
   475                 FilePath::FixPathForPlatform(FBootFields->FAppCDSCacheFileName);
       
   476     }
       
   477 
       
   478     return FBootFields->FAppCDSCacheFileName;
       
   479 }
       
   480 
       
   481 TString Package::GetPackageAppDataDirectory() {
       
   482     assert(FBootFields != NULL);
       
   483     return FBootFields->FPackageAppDataDirectory;
       
   484 }
       
   485 
       
   486 TString Package::GetClassPath() {
       
   487     assert(FBootFields != NULL);
       
   488     return FBootFields->FClassPath;
       
   489 }
       
   490 
       
   491 TString Package::GetModulePath() {
       
   492     assert(FBootFields != NULL);
       
   493     return FBootFields->FModulePath;
       
   494 }
       
   495 
       
   496 TString Package::GetMainJar() {
       
   497     assert(FBootFields != NULL);
       
   498     return FBootFields->FMainJar;
       
   499 }
       
   500 
       
   501 TString Package::GetMainModule() {
       
   502     assert(FBootFields != NULL);
       
   503     return FBootFields->FMainModule;
       
   504 }
       
   505 
       
   506 TString Package::GetMainClassName() {
       
   507     assert(FBootFields != NULL);
       
   508     return FBootFields->FMainClassName;
       
   509 }
       
   510 
       
   511 TString Package::GetJavaLibraryFileName() {
       
   512     assert(FBootFields != NULL);
       
   513 
       
   514     if (FBootFields->FJavaLibraryFileName.empty() == true) {
       
   515         Platform& platform = Platform::GetInstance();
       
   516         Macros& macros = Macros::GetInstance();
       
   517         TString jvmRuntimePath = macros.ExpandMacros(GetJavaRuntimeDirectory());
       
   518         FBootFields->FJavaLibraryFileName =
       
   519                 platform.GetBundledJavaLibraryFileName(jvmRuntimePath);
       
   520     }
       
   521 
       
   522     return FBootFields->FJavaLibraryFileName;
       
   523 }
       
   524 
       
   525 TString Package::GetJavaRuntimeDirectory() {
       
   526     assert(FBootFields != NULL);
       
   527     return FBootFields->FJavaRuntimeDirectory;
       
   528 }
       
   529 
       
   530 TString Package::GetSplashScreenFileName() {
       
   531     assert(FBootFields != NULL);
       
   532     return FBootFields->FSplashScreenFileName;
       
   533 }
       
   534 
       
   535 bool Package::HasSplashScreen() {
       
   536     assert(FBootFields != NULL);
       
   537     return FilePath::FileExists(FBootFields->FSplashScreenFileName);
       
   538 }
       
   539 
       
   540 TString Package::GetCommandName() {
       
   541     assert(FBootFields != NULL);
       
   542     return FBootFields->FCommandName;
       
   543 }
       
   544 
       
   545 TPlatformNumber Package::GetMemorySize() {
       
   546     assert(FBootFields != NULL);
       
   547     return FBootFields->FMemorySize;
       
   548 }
       
   549 
       
   550 PackageBootFields::MemoryState Package::GetMemoryState() {
       
   551     assert(FBootFields != NULL);
       
   552     return FBootFields->FMemoryState;
       
   553 }
       
   554 
       
   555 DebugState Package::Debugging() {
       
   556     return FDebugging;
       
   557 }