--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/src/jdk.jpackager/share/native/library/common/Package.cpp Mon Nov 05 17:32:00 2018 -0500
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include "Package.h"
+#include "Lock.h"
+#include "Helpers.h"
+#include "Macros.h"
+#include "IniFile.h"
+
+#include <assert.h>
+
+
+Package::Package(void) {
+ FInitialized = false;
+ Initialize();
+}
+
+TPlatformNumber StringToPercentageOfNumber(TString Value,
+ TPlatformNumber Number) {
+ TPlatformNumber result = 0;
+ size_t percentage = atoi(PlatformString(Value.c_str()));
+
+ if (percentage > 0 && Number > 0) {
+ result = Number * percentage / 100;
+ }
+
+ return result;
+}
+
+bool Package::CheckForSingleInstance() {
+ Platform& platform = Platform::GetInstance();
+#ifdef MAC
+ if (platform.IsMainThread()) {
+ return false;
+ }
+#endif
+ if (FInitialized == true) {
+ // everything must be initialised at this point
+ return false;
+ }
+ TString appName;
+ TString appVersion;
+ AutoFreePtr<ISectionalPropertyContainer> config =
+ platform.GetConfigFile(platform.GetConfigFileName());
+ std::map<TString, TString> keys = platform.GetKeys();
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[APP_NAME_KEY], appName);
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_VERSION], appVersion);
+ TString singleInstance;
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_APPLICATION_INSTANCE], singleInstance);
+ if (singleInstance == _T("single")) {
+ TString uniqueID = appName + FBootFields->FAppID + appVersion;
+ // if another instance is running, later we can try to reactivate it
+ return platform.CheckForSingleInstance(uniqueID);
+ }
+ return false;
+}
+
+void Package::Initialize() {
+ if (FInitialized == true) {
+ return;
+ }
+
+ Platform& platform = Platform::GetInstance();
+
+ FBootFields = new PackageBootFields();
+ FDebugging = dsNone;
+
+ FBootFields->FPackageRootDirectory = platform.GetPackageRootDirectory();
+ FBootFields->FPackageAppDirectory = platform.GetPackageAppDirectory();
+ FBootFields->FPackageLauncherDirectory =
+ platform.GetPackageLauncherDirectory();
+ FBootFields->FAppDataDirectory = platform.GetAppDataDirectory();
+
+ std::map<TString, TString> keys = platform.GetKeys();
+
+ // Read from configure.cfg/Info.plist
+ AutoFreePtr<ISectionalPropertyContainer> config =
+ platform.GetConfigFile(platform.GetConfigFileName());
+
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_APP_ID_KEY], FBootFields->FAppID);
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[JPACKAGER_APP_DATA_DIR], FBootFields->FPackageAppDataDirectory);
+ FBootFields->FPackageAppDataDirectory =
+ FilePath::FixPathForPlatform(FBootFields->FPackageAppDataDirectory);
+
+ // Main JAR.
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_MAINJAR_KEY], FBootFields->FMainJar);
+ FBootFields->FMainJar =
+ FilePath::IncludeTrailingSeparator(GetPackageAppDirectory())
+ + FilePath::FixPathForPlatform(FBootFields->FMainJar);
+
+ // Main Module.
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_MAINMODULE_KEY], FBootFields->FMainModule);
+
+ // Classpath.
+ // 1. If the provided class path contains main jar then only use
+ // provided class path.
+ // 2. If class path provided by config file is empty then add main jar.
+ // 3. If main jar is not in provided class path then add it.
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_CLASSPATH_KEY], FBootFields->FClassPath);
+ FBootFields->FClassPath =
+ FilePath::FixPathSeparatorForPlatform(FBootFields->FClassPath);
+
+ if (FBootFields->FClassPath.empty() == true) {
+ FBootFields->FClassPath = GetMainJar();
+ } else if (FBootFields->FClassPath.find(GetMainJar()) == TString::npos) {
+ FBootFields->FClassPath = GetMainJar()
+ + FilePath::PathSeparator() + FBootFields->FClassPath;
+ }
+
+ // Modulepath.
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_MODULEPATH_KEY], FBootFields->FModulePath);
+ FBootFields->FModulePath =
+ FilePath::FixPathSeparatorForPlatform(FBootFields->FModulePath);
+
+ // Main Class.
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_MAINCLASSNAME_KEY], FBootFields->FMainClassName);
+
+ // Splash Screen.
+ if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_SPLASH_KEY],
+ FBootFields->FSplashScreenFileName) == true) {
+ FBootFields->FSplashScreenFileName =
+ FilePath::IncludeTrailingSeparator(GetPackageAppDirectory())
+ + FilePath::FixPathForPlatform(FBootFields->FSplashScreenFileName);
+
+ if (FilePath::FileExists(FBootFields->FSplashScreenFileName) == false) {
+ FBootFields->FSplashScreenFileName = _T("");
+ }
+ }
+
+ // Runtime.
+ config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[JVM_RUNTIME_KEY], FBootFields->FJVMRuntimeDirectory);
+
+ // Read jvmargs.
+ PromoteAppCDSState(config);
+ ReadJVMArgs(config);
+
+ // Read args if none were passed in.
+ if (FBootFields->FArgs.size() == 0) {
+ OrderedMap<TString, TString> args;
+
+ if (config->GetSection(keys[CONFIG_SECTION_ARGOPTIONS], args) == true) {
+ FBootFields->FArgs = Helpers::MapToNameValueList(args);
+ }
+ }
+
+ // Auto Memory.
+ TString autoMemory;
+
+ if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_APP_MEMORY], autoMemory) == true) {
+ if (autoMemory == _T("auto") || autoMemory == _T("100%")) {
+ FBootFields->FMemoryState = PackageBootFields::msAuto;
+ FBootFields->FMemorySize = platform.GetMemorySize();
+ } else if (autoMemory.length() == 2 && isdigit(autoMemory[0]) &&
+ autoMemory[1] == '%') {
+ FBootFields->FMemoryState = PackageBootFields::msAuto;
+ FBootFields->FMemorySize =
+ StringToPercentageOfNumber(autoMemory.substr(0, 1),
+ platform.GetMemorySize());
+ } else if (autoMemory.length() == 3 && isdigit(autoMemory[0]) &&
+ isdigit(autoMemory[1]) && autoMemory[2] == '%') {
+ FBootFields->FMemoryState = PackageBootFields::msAuto;
+ FBootFields->FMemorySize =
+ StringToPercentageOfNumber(autoMemory.substr(0, 2),
+ platform.GetMemorySize());
+ } else {
+ FBootFields->FMemoryState = PackageBootFields::msManual;
+ FBootFields->FMemorySize = 0;
+ }
+ }
+
+ // Debug
+ TString debug;
+ if (config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ keys[CONFIG_APP_DEBUG], debug) == true) {
+ FBootFields->FArgs.push_back(debug);
+ }
+}
+
+void Package::Clear() {
+ FreeBootFields();
+ FInitialized = false;
+}
+
+// This is the only location that the AppCDS state should be modified except
+// by command line arguments provided by the user.
+//
+// The state of AppCDS is as follows:
+//
+// -> cdsUninitialized
+// -> cdsGenCache If -Xappcds:generatecache
+// -> cdsDisabled If -Xappcds:off
+// -> cdsEnabled If "AppCDSJVMOptions" section is present
+// -> cdsAuto If "AppCDSJVMOptions" section is present and
+// app.appcds.cache=auto
+// -> cdsDisabled Default
+//
+void Package::PromoteAppCDSState(ISectionalPropertyContainer* Config) {
+ Platform& platform = Platform::GetInstance();
+ std::map<TString, TString> keys = platform.GetKeys();
+
+ // The AppCDS state can change at this point.
+ switch (platform.GetAppCDSState()) {
+ case cdsEnabled:
+ case cdsAuto:
+ case cdsDisabled:
+ case cdsGenCache: {
+ // Do nothing.
+ break;
+ }
+
+ case cdsUninitialized: {
+ if (Config->ContainsSection(
+ keys[CONFIG_SECTION_APPCDSJVMOPTIONS]) == true) {
+ // If the AppCDS section is present then enable AppCDS.
+ TString appCDSCacheValue;
+
+ // If running with AppCDS enabled, and the configuration has
+ // been setup so "auto" is enabled, then
+ // the launcher will attempt to generate the cache file
+ // automatically and run the application.
+ if (Config->GetValue(keys[CONFIG_SECTION_APPLICATION],
+ _T("app.appcds.cache"), appCDSCacheValue) == true &&
+ appCDSCacheValue == _T("auto")) {
+ platform.SetAppCDSState(cdsAuto);
+ }
+ else {
+ platform.SetAppCDSState(cdsEnabled);
+ }
+ } else {
+
+ platform.SetAppCDSState(cdsDisabled);
+ }
+ }
+ }
+}
+
+void Package::ReadJVMArgs(ISectionalPropertyContainer* Config) {
+ Platform& platform = Platform::GetInstance();
+ std::map<TString, TString> keys = platform.GetKeys();
+
+ // Evaluate based on the current AppCDS state.
+ switch (platform.GetAppCDSState()) {
+ case cdsUninitialized: {
+ throw Exception(_T("Internal Error"));
+ }
+
+ case cdsDisabled: {
+ Config->GetSection(keys[CONFIG_SECTION_JVMOPTIONS],
+ FBootFields->FJVMArgs);
+ break;
+ }
+
+ case cdsGenCache: {
+ Config->GetSection(keys[
+ CONFIG_SECTION_APPCDSGENERATECACHEJVMOPTIONS],
+ FBootFields->FJVMArgs);
+ break;
+ }
+
+ case cdsAuto:
+ case cdsEnabled: {
+ if (Config->GetValue(keys[CONFIG_SECTION_APPCDSJVMOPTIONS],
+ _T( "-XX:SharedArchiveFile"),
+ FBootFields->FAppCDSCacheFileName) == true) {
+ // File names may contain the incorrect path separators.
+ // The cache file name must be corrected at this point.
+ if (FBootFields->FAppCDSCacheFileName.empty() == false) {
+ IniFile* iniConfig = dynamic_cast<IniFile*>(Config);
+
+ if (iniConfig != NULL) {
+ FBootFields->FAppCDSCacheFileName =
+ FilePath::FixPathForPlatform(
+ FBootFields->FAppCDSCacheFileName);
+ iniConfig->SetValue(keys[
+ CONFIG_SECTION_APPCDSJVMOPTIONS],
+ _T( "-XX:SharedArchiveFile"),
+ FBootFields->FAppCDSCacheFileName);
+ }
+ }
+
+ Config->GetSection(keys[CONFIG_SECTION_APPCDSJVMOPTIONS],
+ FBootFields->FJVMArgs);
+ }
+
+ break;
+ }
+ }
+}
+
+void Package::SetCommandLineArguments(int argc, TCHAR* argv[]) {
+ if (argc > 0) {
+ std::list<TString> args;
+
+ // Prepare app arguments. Skip value at index 0 -
+ // this is path to executable.
+ FBootFields->FCommandName = argv[0];
+
+ // Path to executable is at 0 index so start at index 1.
+ for (int index = 1; index < argc; index++) {
+ TString arg = argv[index];
+
+#ifdef DEBUG
+ if (arg == _T("-debug")) {
+ FDebugging = dsNative;
+ }
+
+ if (arg == _T("-javadebug")) {
+ FDebugging = dsJava;
+ }
+#endif //DEBUG
+#ifdef MAC
+ if (arg.find(_T("-psn_"), 0) != TString::npos) {
+ Platform& platform = Platform::GetInstance();
+
+ if (platform.IsMainThread() == true) {
+#ifdef DEBUG
+ printf("%s\n", arg.c_str());
+#endif //DEBUG
+ continue;
+ }
+ }
+
+ if (arg == _T("-NSDocumentRevisionsDebugMode")) {
+ // Ignore -NSDocumentRevisionsDebugMode and
+ // the following YES/NO
+ index++;
+ continue;
+ }
+#endif //MAC
+
+ args.push_back(arg);
+ }
+
+ if (args.size() > 0) {
+ FBootFields->FArgs = args;
+ }
+ }
+}
+
+Package& Package::GetInstance() {
+ static Package instance;
+ // Guaranteed to be destroyed. Instantiated on first use.
+ return instance;
+}
+
+Package::~Package(void) {
+ FreeBootFields();
+}
+
+void Package::FreeBootFields() {
+ if (FBootFields != NULL) {
+ delete FBootFields;
+ FBootFields = NULL;
+ }
+}
+
+OrderedMap<TString, TString> Package::GetJVMArgs() {
+ return FBootFields->FJVMArgs;
+}
+
+std::vector<TString> GetKeysThatAreNotDuplicates(OrderedMap<TString,
+ TString> &Defaults, OrderedMap<TString, TString> &Overrides) {
+ std::vector<TString> result;
+ std::vector<TString> overrideKeys = Overrides.GetKeys();
+
+ for (size_t index = 0; index < overrideKeys.size(); index++) {
+ TString overridesKey = overrideKeys[index];
+ TString overridesValue;
+ TString defaultValue;
+
+ if ((Defaults.ContainsKey(overridesKey) == false) ||
+ (Defaults.GetValue(overridesKey, defaultValue) == true &&
+ Overrides.GetValue(overridesKey, overridesValue) == true &&
+ defaultValue != overridesValue)) {
+ result.push_back(overridesKey);
+ }
+ }
+
+ return result;
+}
+
+OrderedMap<TString, TString> CreateOrderedMapFromKeyList(OrderedMap<TString,
+ TString> &Map, std::vector<TString> &Keys) {
+ OrderedMap<TString, TString> result;
+
+ for (size_t index = 0; index < Keys.size(); index++) {
+ TString key = Keys[index];
+ TString value;
+
+ if (Map.GetValue(key, value) == true) {
+ result.Append(key, value);
+ }
+ }
+
+ return result;
+}
+
+std::vector<TString> GetKeysThatAreNotOverridesOfDefaultValues(
+ OrderedMap<TString, TString> &Defaults, OrderedMap<TString,
+ TString> &Overrides) {
+ std::vector<TString> result;
+ std::vector<TString> keys = Overrides.GetKeys();
+
+ for (unsigned int index = 0; index< keys.size(); index++) {
+ TString key = keys[index];
+
+ if (Defaults.ContainsKey(key) == true) {
+ try {
+ TString value = Overrides[key];
+ Defaults[key] = value;
+ }
+ catch (std::out_of_range) {
+ }
+ }
+ else {
+ result.push_back(key);
+ }
+ }
+
+ return result;
+}
+
+std::list<TString> Package::GetArgs() {
+ assert(FBootFields != NULL);
+ return FBootFields->FArgs;
+}
+
+TString Package::GetPackageRootDirectory() {
+ assert(FBootFields != NULL);
+ return FBootFields->FPackageRootDirectory;
+}
+
+TString Package::GetPackageAppDirectory() {
+ assert(FBootFields != NULL);
+ return FBootFields->FPackageAppDirectory;
+}
+
+TString Package::GetPackageLauncherDirectory() {
+ assert(FBootFields != NULL);
+ return FBootFields->FPackageLauncherDirectory;
+}
+
+TString Package::GetAppDataDirectory() {
+ assert(FBootFields != NULL);
+ return FBootFields->FAppDataDirectory;
+}
+
+TString Package::GetAppCDSCacheDirectory() {
+ if (FAppCDSCacheDirectory.empty()) {
+ Platform& platform = Platform::GetInstance();
+ FAppCDSCacheDirectory = FilePath::IncludeTrailingSeparator(
+ platform.GetAppDataDirectory())
+ + FilePath::IncludeTrailingSeparator(
+ GetPackageAppDataDirectory()) + _T("cache");
+
+ Macros& macros = Macros::GetInstance();
+ FAppCDSCacheDirectory = macros.ExpandMacros(FAppCDSCacheDirectory);
+ FAppCDSCacheDirectory =
+ FilePath::FixPathForPlatform(FAppCDSCacheDirectory);
+ }
+
+ return FAppCDSCacheDirectory;
+}
+
+TString Package::GetAppCDSCacheFileName() {
+ assert(FBootFields != NULL);
+
+ if (FBootFields->FAppCDSCacheFileName.empty() == false) {
+ Macros& macros = Macros::GetInstance();
+ FBootFields->FAppCDSCacheFileName =
+ macros.ExpandMacros(FBootFields->FAppCDSCacheFileName);
+ FBootFields->FAppCDSCacheFileName =
+ FilePath::FixPathForPlatform(FBootFields->FAppCDSCacheFileName);
+ }
+
+ return FBootFields->FAppCDSCacheFileName;
+}
+
+TString Package::GetAppID() {
+ assert(FBootFields != NULL);
+ return FBootFields->FAppID;
+}
+
+TString Package::GetPackageAppDataDirectory() {
+ assert(FBootFields != NULL);
+ return FBootFields->FPackageAppDataDirectory;
+}
+
+TString Package::GetClassPath() {
+ assert(FBootFields != NULL);
+ return FBootFields->FClassPath;
+}
+
+TString Package::GetModulePath() {
+ assert(FBootFields != NULL);
+ return FBootFields->FModulePath;
+}
+
+TString Package::GetMainJar() {
+ assert(FBootFields != NULL);
+ return FBootFields->FMainJar;
+}
+
+TString Package::GetMainModule() {
+ assert(FBootFields != NULL);
+ return FBootFields->FMainModule;
+}
+
+TString Package::GetMainClassName() {
+ assert(FBootFields != NULL);
+ return FBootFields->FMainClassName;
+}
+
+TString Package::GetJVMLibraryFileName() {
+ assert(FBootFields != NULL);
+
+ if (FBootFields->FJVMLibraryFileName.empty() == true) {
+ Platform& platform = Platform::GetInstance();
+ Macros& macros = Macros::GetInstance();
+ TString jvmRuntimePath = macros.ExpandMacros(GetJVMRuntimeDirectory());
+ FBootFields->FJVMLibraryFileName =
+ platform.GetBundledJVMLibraryFileName(jvmRuntimePath);
+ }
+
+ return FBootFields->FJVMLibraryFileName;
+}
+
+TString Package::GetJVMRuntimeDirectory() {
+ assert(FBootFields != NULL);
+ return FBootFields->FJVMRuntimeDirectory;
+}
+
+TString Package::GetSplashScreenFileName() {
+ assert(FBootFields != NULL);
+ return FBootFields->FSplashScreenFileName;
+}
+
+bool Package::HasSplashScreen() {
+ assert(FBootFields != NULL);
+ return FilePath::FileExists(FBootFields->FSplashScreenFileName);
+}
+
+TString Package::GetCommandName() {
+ assert(FBootFields != NULL);
+ return FBootFields->FCommandName;
+}
+
+TPlatformNumber Package::GetMemorySize() {
+ assert(FBootFields != NULL);
+ return FBootFields->FMemorySize;
+}
+
+PackageBootFields::MemoryState Package::GetMemoryState() {
+ assert(FBootFields != NULL);
+ return FBootFields->FMemoryState;
+}
+
+DebugState Package::Debugging() {
+ return FDebugging;
+}