8242302: Refactor jpackage native code

Reviewed-by: herrick, almatvee, erikj
This commit is contained in:
Alexey Semenyuk 2020-04-23 16:40:09 -04:00
parent 90ada6a314
commit 0c56c3511a
91 changed files with 2894 additions and 8946 deletions

View File

@ -1,5 +1,5 @@
# #
# Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. # Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
@ -27,48 +27,43 @@ include LibCommon.gmk
################################################################################ ################################################################################
# Output app launcher library in resources dir, and symbols in the object dir
$(eval $(call SetupJdkLibrary, BUILD_LIB_APPLAUNCHER, \
NAME := applauncher, \
OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libapplauncher, \
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
OPTIMIZATION := LOW, \
CFLAGS := $(CXXFLAGS_JDKLIB) $(X_CFLAGS), \
CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := $(LIBCXX), \
LIBS_windows := user32.lib shell32.lib advapi32.lib ole32.lib, \
LIBS_linux := -ldl -lpthread, \
LIBS_macosx := -ldl -framework Cocoa, \
))
$(BUILD_LIB_APPLAUNCHER): $(call FindLib, java.base, java)
TARGETS += $(BUILD_LIB_APPLAUNCHER)
JPACKAGE_APPLAUNCHER_SRC := \ JPACKAGE_APPLAUNCHER_SRC := \
$(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/jpackageapplauncher $(call FindSrcDirsForComponent, jdk.incubator.jpackage, applauncher) \
$(call FindSrcDirsForComponent, jdk.incubator.jpackage, common)
ifeq ($(call isTargetOs, windows), true)
JpackageWithStaticCrt = \
$(filter-out -MD, $1) -MT
else
JpackageWithStaticCrt = \
$1
endif
JPACKAGE_OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources
JPACKAGE_CXXFLAGS_windows := -EHsc -DUNICODE -D_UNICODE
# Output app launcher executable in resources dir, and symbols in the object dir # Output app launcher executable in resources dir, and symbols in the object dir
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \ $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \
NAME := jpackageapplauncher, \ NAME := jpackageapplauncher, \
OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \ OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncher, \ SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncher, \
SRC := $(JPACKAGE_APPLAUNCHER_SRC), \ SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
OPTIMIZATION := LOW, \ OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKEXE), \ CXXFLAGS := $(call JpackageWithStaticCrt, $(CXXFLAGS_JDKEXE)) \
CXXFLAGS := $(CXXFLAGS_JDKEXE), \ $(addprefix -I, $(JPACKAGE_APPLAUNCHER_SRC)), \
CFLAGS_windows := -EHsc -DLAUNCHERC -DUNICODE -D_UNICODE, \ CXXFLAGS_windows := $(JPACKAGE_CXXFLAGS_windows), \
LDFLAGS := $(LDFLAGS_JDKEXE), \ LDFLAGS := $(LDFLAGS_JDKEXE), \
LIBS_macosx := -framework Cocoa, \ LIBS_macosx := -framework Cocoa, \
LIBS := $(LIBCXX), \ LIBS := $(LIBCXX), \
LIBS_linux := -ldl, \ LIBS_linux := -ldl, \
LIBS_windows := user32.lib shell32.lib advapi32.lib, \
)) ))
$(BUILD_JPACKAGE_APPLAUNCHEREXE): $(call FindLib, java.base, java)
TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE) TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE)
################################################################################ ################################################################################
@ -78,12 +73,11 @@ ifeq ($(call isTargetOs, windows), true)
$(eval $(call SetupJdkLibrary, BUILD_LIB_JPACKAGE, \ $(eval $(call SetupJdkLibrary, BUILD_LIB_JPACKAGE, \
NAME := jpackage, \ NAME := jpackage, \
OPTIMIZATION := LOW, \ OPTIMIZATION := LOW, \
CFLAGS := $(CXXFLAGS_JDKLIB), \ EXTRA_SRC := jdk.incubator.jpackage:common, \
CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \ CXXFLAGS := $(CXXFLAGS_JDKLIB) $(JPACKAGE_CXXFLAGS_windows), \
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
$(call SET_SHARED_LIBRARY_ORIGIN), \ $(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := $(LIBCXX), \ LIBS := $(LIBCXX), \
LIBS_windows := user32.lib shell32.lib advapi32.lib ole32.lib, \
)) ))
TARGETS += $(BUILD_LIB_JPACKAGE) TARGETS += $(BUILD_LIB_JPACKAGE)
@ -92,11 +86,11 @@ ifeq ($(call isTargetOs, windows), true)
# Output library in resources dir, and symbols in the object dir # Output library in resources dir, and symbols in the object dir
$(eval $(call SetupJdkLibrary, BUILD_LIB_WIXHELPER, \ $(eval $(call SetupJdkLibrary, BUILD_LIB_WIXHELPER, \
NAME := wixhelper, \ NAME := wixhelper, \
OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \ OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libwixhelper, \ SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libwixhelper, \
OPTIMIZATION := LOW, \ OPTIMIZATION := LOW, \
CFLAGS := $(CXXFLAGS_JDKLIB), \ CXXFLAGS := $(call JpackageWithStaticCrt, $(CXXFLAGS_JDKLIB)) \
CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE -MT, \ $(JPACKAGE_CXXFLAGS_windows), \
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \ LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \
LIBS := $(LIBCXX), \ LIBS := $(LIBCXX), \
LIBS_windows := msi.lib Shlwapi.lib User32.lib, \ LIBS_windows := msi.lib Shlwapi.lib User32.lib, \
@ -104,17 +98,18 @@ ifeq ($(call isTargetOs, windows), true)
TARGETS += $(BUILD_LIB_WIXHELPER) TARGETS += $(BUILD_LIB_WIXHELPER)
JPACKAGE_MSIWRAPPER_SRC := \
$(call FindSrcDirsForComponent, jdk.incubator.jpackage, msiwrapper) \
$(call FindSrcDirsForComponent, jdk.incubator.jpackage, common)
# Build exe installer wrapper for msi installer # Build exe installer wrapper for msi installer
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_MSIWRAPPER, \ $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_MSIWRAPPER, \
NAME := msiwrapper, \ NAME := msiwrapper, \
OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \ OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/msiwrapper, \ SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/msiwrapper, \
SRC := $(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/msiwrapper, \ SRC := $(JPACKAGE_MSIWRAPPER_SRC), \
EXTRA_FILES := $(addprefix $(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/libjpackage/, \ CXXFLAGS := $(call JpackageWithStaticCrt, $(CXXFLAGS_JDKEXE)) \
FileUtils.cpp Log.cpp WinSysInfo.cpp tstrings.cpp WinErrorHandling.cpp ErrorHandling.cpp), \ $(addprefix -I, $(JPACKAGE_MSIWRAPPER_SRC)) $(JPACKAGE_CXXFLAGS_windows), \
CFLAGS := $(CXXFLAGS_JDKEXE) -MT \
$(addprefix -I$(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/, msiwrapper libjpackage), \
CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
LDFLAGS := $(LDFLAGS_JDKEXE), \ LDFLAGS := $(LDFLAGS_JDKEXE), \
LIBS := $(LIBCXX), \ LIBS := $(LIBCXX), \
)) ))
@ -123,18 +118,17 @@ ifeq ($(call isTargetOs, windows), true)
# Build non-console version of launcher # Build non-console version of launcher
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHERWEXE, \ $(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHERWEXE, \
NAME := jpackageapplauncherw, \ NAME := jpackageapplauncherw, \
OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \ OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \ SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \
SRC := $(JPACKAGE_APPLAUNCHER_SRC), \ SRC := $(BUILD_JPACKAGE_APPLAUNCHEREXE_SRC), \
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \ TOOLCHAIN := $(BUILD_JPACKAGE_APPLAUNCHEREXE_TOOLCHAIN), \
OPTIMIZATION := LOW, \ OPTIMIZATION := $(BUILD_JPACKAGE_APPLAUNCHEREXE_OPTIMIZATION), \
CFLAGS := $(CXXFLAGS_JDKEXE), \ CXXFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS), \
CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \ CXXFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS_windows) -DJP_LAUNCHERW, \
LDFLAGS := $(LDFLAGS_JDKEXE), \ LDFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LDFLAGS), \
LIBS := $(LIBCXX), \ LIBS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS), \
LIBS_windows := user32.lib shell32.lib advapi32.lib, \ ))
))
TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE) TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE)

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -40,7 +40,6 @@ import static jdk.incubator.jpackage.internal.StandardBundlerParam.*;
public class LinuxAppImageBuilder extends AbstractAppImageBuilder { public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
private static final String LIBRARY_NAME = "libapplauncher.so";
final static String DEFAULT_ICON = "java32.png"; final static String DEFAULT_ICON = "java32.png";
private final ApplicationLayout appLayout; private final ApplicationLayout appLayout;
@ -109,11 +108,6 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
// create the primary launcher // create the primary launcher
createLauncherForEntryPoint(params, null); createLauncherForEntryPoint(params, null);
// Copy library to the launcher folder
try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
writeEntry(is_lib, appLayout.dllDirectory().resolve(LIBRARY_NAME));
}
// create the additional launchers, if any // create the additional launchers, if any
List<Map<String, ? super Object>> entryPoints List<Map<String, ? super Object>> entryPoints
= StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params); = StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,39 +23,36 @@
* questions. * questions.
*/ */
#ifndef PLATFORM_DEFS_H #include "AppLauncher.h"
#define PLATFORM_DEFS_H #include "FileUtils.h"
#include "UnixSysInfo.h"
// Define Windows compatibility requirements XP or later
#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#include <Windows.h> namespace {
#include <tchar.h>
#include <shlobj.h>
#include <direct.h>
#include <process.h>
#include <malloc.h>
#include <string>
using namespace std; void launchApp() {
setlocale(LC_ALL, "en_US.utf8");
#ifndef WINDOWS const tstring launcherPath = SysInfo::getProcessModulePath();
#define WINDOWS
#endif
typedef std::wstring TString; // Launcher should be in "bin" subdirectory of app image.
#define StringLength wcslen const tstring appImageRoot = FileUtils::dirname(
FileUtils::dirname(launcherPath));
#define TRAILING_PATHSEPARATOR '\\' AppLauncher()
#define BAD_TRAILING_PATHSEPARATOR '/' .setImageRoot(appImageRoot)
#define PATH_SEPARATOR ';' .addJvmLibName(_T("lib/libjli.so"))
#define BAD_PATH_SEPARATOR ':' .setAppDir(FileUtils::mkpath() << appImageRoot << _T("lib/app"))
.setDefaultRuntimePath(FileUtils::mkpath() << appImageRoot
<< _T("lib/runtime"))
.launch();
}
typedef ULONGLONG TPlatformNumber; } // namespace
typedef DWORD TProcessID;
typedef void* Module;
typedef void* Procedure;
#endif // PLATFORM_DEFS_H int main(int argc, char *argv[]) {
SysInfo::argc = argc;
SysInfo::argv = argv;
return AppLauncher::launch(std::nothrow, launchApp);
}

View File

@ -0,0 +1,45 @@
/*
* Copyright (c) 2020, 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 <limits.h>
#include <unistd.h>
#include "FileUtils.h"
#include "ErrorHandling.h"
namespace SysInfo {
tstring getProcessModulePath() {
const char* path = "/proc/self/exe";
char buffer[PATH_MAX] = { 0 };
ssize_t len = readlink(path, buffer, sizeof(buffer));
if (len < 0) {
JP_THROW(tstrings::any() << "readlink(" << path
<< ") failed. Error: " << lastCRTError());
}
return tstring(buffer, len);
}
} // end of namespace SysInfo

View File

@ -1,87 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 <dlfcn.h>
#include <locale.h>
#include <string>
#include <libgen.h>
#include <stdio.h>
#include <unistd.h>
typedef bool (*start_launcher)(int argc, char* argv[]);
typedef void (*stop_launcher)();
#define MAX_PATH 1024
std::string GetProgramPath() {
ssize_t len = 0;
std::string result;
char buffer[MAX_PATH] = {0};
if ((len = readlink("/proc/self/exe", buffer, MAX_PATH - 1)) != -1) {
buffer[len] = '\0';
result = buffer;
}
return result;
}
int main(int argc, char *argv[]) {
int result = 1;
setlocale(LC_ALL, "en_US.utf8");
void* library = NULL;
{
std::string programPath = GetProgramPath();
std::string libraryName = dirname((char*)programPath.c_str());
libraryName += "/../lib/libapplauncher.so";
library = dlopen(libraryName.c_str(), RTLD_LAZY);
if (library == NULL) {
fprintf(stderr, "dlopen failed: %s\n", dlerror());
fprintf(stderr, "%s not found.\n", libraryName.c_str());
}
}
if (library != NULL) {
start_launcher start = (start_launcher)dlsym(library, "start_launcher");
stop_launcher stop = (stop_launcher)dlsym(library, "stop_launcher");
if (start != NULL && stop != NULL) {
if (start(argc, argv) == true) {
result = 0;
stop();
}
} else {
fprintf(stderr, "cannot find start_launcher and stop_launcher in libapplauncher.so");
}
dlclose(library);
}
return result;
}

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef LINUXPLATFORM_H
#define LINUXPLATFORM_H
#include "Platform.h"
#include "PosixPlatform.h"
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <pthread.h>
#include <list>
class LinuxPlatform : virtual public Platform, PosixPlatform {
private:
pthread_t FMainThread;
protected:
virtual TString getTmpDirString();
public:
LinuxPlatform(void);
virtual ~LinuxPlatform(void);
TString GetPackageAppDirectory();
TString GetPackageLauncherDirectory();
TString GetPackageRuntimeBinDirectory();
virtual void ShowMessage(TString title, TString description);
virtual void ShowMessage(TString description);
virtual TCHAR* ConvertStringToFileSystemString(
TCHAR* Source, bool &release);
virtual TCHAR* ConvertFileSystemStringToString(
TCHAR* Source, bool &release);
virtual TString GetPackageRootDirectory();
virtual TString GetAppDataDirectory();
virtual TString GetAppName();
virtual TString GetModuleFileName();
virtual TString GetBundledJavaLibraryFileName(TString RuntimePath);
virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
virtual bool IsMainThread();
virtual TPlatformNumber GetMemorySize();
};
#endif //LINUXPLATFORM_H

View File

@ -65,7 +65,6 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
private static final ResourceBundle I18N = ResourceBundle.getBundle( private static final ResourceBundle I18N = ResourceBundle.getBundle(
"jdk.incubator.jpackage.internal.resources.MacResources"); "jdk.incubator.jpackage.internal.resources.MacResources");
private static final String LIBRARY_NAME = "libapplauncher.dylib";
private static final String TEMPLATE_BUNDLE_ICON = "java.icns"; private static final String TEMPLATE_BUNDLE_ICON = "java.icns";
private static final String OS_TYPE_CODE = "APPL"; private static final String OS_TYPE_CODE = "APPL";
private static final String TEMPLATE_INFO_PLIST_LITE = private static final String TEMPLATE_INFO_PLIST_LITE =
@ -265,11 +264,9 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
// create the main app launcher // create the main app launcher
try (InputStream is_launcher = try (InputStream is_launcher =
getResourceAsStream("jpackageapplauncher"); getResourceAsStream("jpackageapplauncher")) {
InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
// Copy executable and library to MacOS folder // Copy executable and library to MacOS folder
writeEntry(is_launcher, executable); writeEntry(is_launcher, executable);
writeEntry(is_lib, macOSDir.resolve(LIBRARY_NAME));
} }
executable.toFile().setExecutable(true, false); executable.toFile().setExecutable(true, false);
// generate main app launcher config file // generate main app launcher config file

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2020, 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 "AppLauncher.h"
#include "FileUtils.h"
#include "UnixSysInfo.h"
#include "JvmLauncher.h"
namespace {
Jvm* jvmLauncher = 0;
void launchJvm() {
// On Mac JLI_Launch() spawns a new thread that actually starts the JVM.
// This new thread simply re-runs launcher's main() function with
// arguments passed into JLI_Launch() call.
// Jvm::launch() calls JLI_Launch() triggering thread spawning.
jvmLauncher->launch();
}
void initJvmLauncher() {
const tstring launcherPath = SysInfo::getProcessModulePath();
// Launcher should be in "Contents/MacOS" subdirectory of app image.
// However, don't strip "Contents" folder from launcher path, so that app
// image root directory would be set to "Contents" subfolder of app image.
const tstring appImageRoot = FileUtils::dirname(
FileUtils::dirname(launcherPath));
// Create JVM launcher and save in global variable.
jvmLauncher = AppLauncher()
.setImageRoot(appImageRoot)
.addJvmLibName(_T("Contents/Home/lib/libjli.dylib"))
.setAppDir(FileUtils::mkpath() << appImageRoot << _T("app"))
.setDefaultRuntimePath(FileUtils::mkpath() << appImageRoot
<< _T("runtime"))
.createJvmLauncher();
// Kick start JVM launching. The function wouldn't return!
launchJvm();
}
} // namespace
int main(int argc, char *argv[]) {
setlocale(LC_ALL, "en_US.utf8");
if (jvmLauncher) {
// This is the call from the thread spawned by JVM.
// Skip initialization phase as we have done this already in the first
// call of main().
// Besides we should ignore main() arguments because these are the
// arguments passed into JLI_Launch() call and not the arguments with
// which the launcher was started.
return AppLauncher::launch(std::nothrow, launchJvm);
}
SysInfo::argc = argc;
SysInfo::argv = argv;
return AppLauncher::launch(std::nothrow, initJvmLauncher);
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2020, 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 <mach-o/dyld.h>
#include "FileUtils.h"
#include "ErrorHandling.h"
namespace SysInfo {
tstring getProcessModulePath() {
std::vector<char> buffer;
uint32_t bufferSize = 0;
do {
int len = _NSGetExecutablePath(buffer.data(), &bufferSize);
if (len == 0) {
break;
}
if (len > 0) {
JP_THROW(tstrings::any() << "_NSGetExecutablePath() failed");
}
buffer.resize(bufferSize);
} while (true);
tstring reply = tstring(buffer.data(),
buffer.size() - 1 /* don't count trailing '0' */);
return FileUtils::toAbsolutePath(reply);
}
} // end of namespace SysInfo

View File

@ -1,81 +0,0 @@
/*
* Copyright (c) 2012, 2019, 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.
*/
#import <Cocoa/Cocoa.h>
#include <dlfcn.h>
#include <unistd.h>
typedef bool (*start_launcher)(int argc, char* argv[]);
typedef void (*stop_launcher)();
int main(int argc, char *argv[]) {
#if !__has_feature(objc_arc)
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#endif
int result = 1;
@try {
setlocale(LC_ALL, "en_US.utf8");
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *mainBundlePath = [mainBundle bundlePath];
NSString *libraryName = [mainBundlePath stringByAppendingPathComponent:@"Contents/MacOS/libapplauncher.dylib"];
void* library = dlopen([libraryName UTF8String], RTLD_LAZY);
if (library == NULL) {
NSLog(@"%@ not found.\n", libraryName);
}
if (library != NULL) {
start_launcher start =
(start_launcher)dlsym(library, "start_launcher");
stop_launcher stop =
(stop_launcher)dlsym(library, "stop_launcher");
if (start != NULL && stop != NULL) {
if (start(argc, argv) == true) {
result = 0;
stop();
}
} else if (start == NULL) {
NSLog(@"start_launcher not found in %@.\n", libraryName);
} else {
NSLog(@"stop_launcher not found in %@.\n", libraryName);
}
dlclose(library);
}
} @catch (NSException *exception) {
NSLog(@"%@: %@", exception, [exception callStackSymbols]);
result = 1;
}
#if !__has_feature(objc_arc)
[pool drain];
#endif
return result;
}

View File

@ -1,71 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef MACPLATFORM_H
#define MACPLATFORM_H
#include "Platform.h"
#include "PosixPlatform.h"
class MacPlatform : virtual public Platform, PosixPlatform {
private:
bool UsePListForConfigFile();
protected:
virtual TString getTmpDirString();
public:
MacPlatform(void);
virtual ~MacPlatform(void);
public:
virtual void ShowMessage(TString title, TString description);
virtual void ShowMessage(TString description);
virtual TCHAR* ConvertStringToFileSystemString(
TCHAR* Source, bool &release);
virtual TCHAR* ConvertFileSystemStringToString(
TCHAR* Source, bool &release);
virtual TString GetPackageRootDirectory();
virtual TString GetAppDataDirectory();
virtual TString GetBundledJavaLibraryFileName(TString RuntimePath);
virtual TString GetAppName();
TString GetPackageAppDirectory();
TString GetPackageLauncherDirectory();
TString GetPackageRuntimeBinDirectory();
virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
virtual TString GetModuleFileName();
virtual bool IsMainThread();
virtual TPlatformNumber GetMemorySize();
virtual std::map<TString, TString> GetKeys();
};
#endif // MACPLATFORM_H

View File

@ -1,505 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "Platform.h"
#include "MacPlatform.h"
#include "Helpers.h"
#include "Package.h"
#include "PropertyFile.h"
#include "IniFile.h"
#include <sys/sysctl.h>
#include <pthread.h>
#include <vector>
#include <signal.h>
#include <mach-o/dyld.h>
#import <Foundation/Foundation.h>
#import <AppKit/NSRunningApplication.h>
#include <CoreFoundation/CoreFoundation.h>
#include <CoreFoundation/CFString.h>
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif //__OBJC__
#define MAC_JPACKAGE_TMP_DIR \
"/Library/Application Support/Java/JPackage/tmp"
NSString* StringToNSString(TString Value) {
NSString* result = [NSString stringWithCString : Value.c_str()
encoding : [NSString defaultCStringEncoding]];
return result;
}
FileSystemStringToString::FileSystemStringToString(const TCHAR* value) {
bool release = false;
PlatformString lvalue = PlatformString(value);
Platform& platform = Platform::GetInstance();
TCHAR* buffer = platform.ConvertFileSystemStringToString(lvalue, release);
FData = buffer;
if (buffer != NULL && release == true) {
delete[] buffer;
}
}
FileSystemStringToString::operator TString() {
return FData;
}
StringToFileSystemString::StringToFileSystemString(const TString &value) {
FRelease = false;
PlatformString lvalue = PlatformString(value);
Platform& platform = Platform::GetInstance();
FData = platform.ConvertStringToFileSystemString(lvalue, FRelease);
}
StringToFileSystemString::~StringToFileSystemString() {
if (FRelease == true) {
delete[] FData;
}
}
StringToFileSystemString::operator TCHAR* () {
return FData;
}
MacPlatform::MacPlatform(void) : Platform(), PosixPlatform() {
}
MacPlatform::~MacPlatform(void) {
}
TString MacPlatform::GetPackageAppDirectory() {
return FilePath::IncludeTrailingSeparator(
GetPackageRootDirectory()) + _T("app");
}
TString MacPlatform::GetPackageLauncherDirectory() {
return FilePath::IncludeTrailingSeparator(
GetPackageRootDirectory()) + _T("MacOS");
}
TString MacPlatform::GetPackageRuntimeBinDirectory() {
return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory()) +
_T("runtime/Contents/Home/bin");
}
bool MacPlatform::UsePListForConfigFile() {
return FilePath::FileExists(GetConfigFileName()) == false;
}
void MacPlatform::ShowMessage(TString Title, TString Description) {
NSString *ltitle = StringToNSString(Title);
NSString *ldescription = StringToNSString(Description);
NSLog(@"%@:%@", ltitle, ldescription);
}
void MacPlatform::ShowMessage(TString Description) {
TString appname = GetModuleFileName();
appname = FilePath::ExtractFileName(appname);
ShowMessage(appname, Description);
}
TString MacPlatform::getTmpDirString() {
return TString(MAC_JPACKAGE_TMP_DIR);
}
TCHAR* MacPlatform::ConvertStringToFileSystemString(TCHAR* Source,
bool &release) {
TCHAR* result = NULL;
release = false;
CFStringRef StringRef = CFStringCreateWithCString(kCFAllocatorDefault,
Source, kCFStringEncodingUTF8);
if (StringRef != NULL) {
@ try {
CFIndex length =
CFStringGetMaximumSizeOfFileSystemRepresentation(StringRef);
result = new char[length + 1];
if (result != NULL) {
if (CFStringGetFileSystemRepresentation(StringRef,
result, length)) {
release = true;
} else {
delete[] result;
result = NULL;
}
}
}
@finally
{
CFRelease(StringRef);
}
}
return result;
}
TCHAR* MacPlatform::ConvertFileSystemStringToString(TCHAR* Source,
bool &release) {
TCHAR* result = NULL;
release = false;
CFStringRef StringRef = CFStringCreateWithFileSystemRepresentation(
kCFAllocatorDefault, Source);
if (StringRef != NULL) {
@ try {
CFIndex length = CFStringGetLength(StringRef);
if (length > 0) {
CFIndex maxSize = CFStringGetMaximumSizeForEncoding(
length, kCFStringEncodingUTF8);
result = new char[maxSize + 1];
if (result != NULL) {
if (CFStringGetCString(StringRef, result, maxSize,
kCFStringEncodingUTF8) == true) {
release = true;
} else {
delete[] result;
result = NULL;
}
}
}
}
@finally
{
CFRelease(StringRef);
}
}
return result;
}
TString MacPlatform::GetPackageRootDirectory() {
NSBundle *mainBundle = [NSBundle mainBundle];
NSString *mainBundlePath = [mainBundle bundlePath];
NSString *contentsPath =
[mainBundlePath stringByAppendingString : @"/Contents"];
TString result = [contentsPath UTF8String];
return result;
}
TString MacPlatform::GetAppDataDirectory() {
TString result;
NSArray *paths = NSSearchPathForDirectoriesInDomains(
NSApplicationSupportDirectory, NSUserDomainMask, YES);
NSString *applicationSupportDirectory = [paths firstObject];
result = [applicationSupportDirectory UTF8String];
return result;
}
TString MacPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) {
TString result;
// first try lib/, then lib/jli
result = FilePath::IncludeTrailingSeparator(RuntimePath) +
_T("Contents/Home/lib/libjli.dylib");
if (FilePath::FileExists(result) == false) {
result = FilePath::IncludeTrailingSeparator(RuntimePath) +
_T("Contents/Home/lib/jli/libjli.dylib");
if (FilePath::FileExists(result) == false) {
// cannot find
NSLog(@"Cannot find libjli.dysym!");
result = _T("");
}
}
return result;
}
TString MacPlatform::GetAppName() {
NSString *appName = [[NSProcessInfo processInfo] processName];
TString result = [appName UTF8String];
return result;
}
void PosixProcess::Cleanup() {
if (FOutputHandle != 0) {
close(FOutputHandle);
FOutputHandle = 0;
}
if (FInputHandle != 0) {
close(FInputHandle);
FInputHandle = 0;
}
sigaction(SIGINT, &savintr, (struct sigaction *) 0);
sigaction(SIGQUIT, &savequit, (struct sigaction *) 0);
sigprocmask(SIG_SETMASK, &saveblock, (sigset_t *) 0);
}
#define PIPE_READ 0
#define PIPE_WRITE 1
bool PosixProcess::Execute(const TString Application,
const std::vector<TString> Arguments, bool AWait) {
bool result = false;
if (FRunning == false) {
FRunning = true;
int handles[2];
if (pipe(handles) == -1) {
return false;
}
struct sigaction sa;
sa.sa_handler = SIG_IGN;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigemptyset(&savintr.sa_mask);
sigemptyset(&savequit.sa_mask);
sigaction(SIGINT, &sa, &savintr);
sigaction(SIGQUIT, &sa, &savequit);
sigaddset(&sa.sa_mask, SIGCHLD);
sigprocmask(SIG_BLOCK, &sa.sa_mask, &saveblock);
FChildPID = fork();
// PID returned by vfork is 0 for the child process and the
// PID of the child process for the parent.
if (FChildPID == -1) {
// Error
TString message = PlatformString::Format(
_T("Error: Unable to create process %s"),
Application.data());
throw Exception(message);
} else if (FChildPID == 0) {
Cleanup();
TString command = Application;
for (std::vector<TString>::const_iterator iterator =
Arguments.begin(); iterator != Arguments.end();
iterator++) {
command += TString(_T(" ")) + *iterator;
}
#ifdef DEBUG
printf("%s\n", command.data());
#endif // DEBUG
dup2(handles[PIPE_READ], STDIN_FILENO);
dup2(handles[PIPE_WRITE], STDOUT_FILENO);
close(handles[PIPE_READ]);
close(handles[PIPE_WRITE]);
execl("/bin/sh", "sh", "-c", command.data(), (char *) 0);
_exit(127);
} else {
FOutputHandle = handles[PIPE_READ];
FInputHandle = handles[PIPE_WRITE];
if (AWait == true) {
ReadOutput();
Wait();
Cleanup();
FRunning = false;
result = true;
} else {
result = true;
}
}
}
return result;
}
void AppendPListArrayToIniFile(NSDictionary *infoDictionary,
IniFile *result, TString Section) {
NSString *sectionKey =
[NSString stringWithUTF8String : PlatformString(Section).toMultibyte()];
NSDictionary *array = [infoDictionary objectForKey : sectionKey];
for (id option in array) {
if ([option isKindOfClass : [NSString class]]) {
TString arg = [option UTF8String];
TString name;
TString value;
if (Helpers::SplitOptionIntoNameValue(arg, name, value) == true) {
result->Append(Section, name, value);
}
}
}
}
void AppendPListDictionaryToIniFile(NSDictionary *infoDictionary,
IniFile *result, TString Section, bool FollowSection = true) {
NSDictionary *dictionary = NULL;
if (FollowSection == true) {
NSString *sectionKey = [NSString stringWithUTF8String : PlatformString(
Section).toMultibyte()];
dictionary = [infoDictionary objectForKey : sectionKey];
} else {
dictionary = infoDictionary;
}
for (id key in dictionary) {
id option = [dictionary valueForKey : key];
if ([key isKindOfClass : [NSString class]] &&
[option isKindOfClass : [NSString class]]) {
TString name = [key UTF8String];
TString value = [option UTF8String];
result->Append(Section, name, value);
}
}
}
// Convert parts of the info.plist to the INI format the rest of the jpackage
// uses unless a jpackage config file exists.
ISectionalPropertyContainer* MacPlatform::GetConfigFile(TString FileName) {
IniFile* result = new IniFile();
if (result == NULL) {
return NULL;
}
if (UsePListForConfigFile() == false) {
result->LoadFromFile(FileName);
} else {
NSBundle *mainBundle = [NSBundle mainBundle];
NSDictionary *infoDictionary = [mainBundle infoDictionary];
std::map<TString, TString> keys = GetKeys();
// JPackage options.
AppendPListDictionaryToIniFile(infoDictionary, result,
keys[CONFIG_SECTION_APPLICATION], false);
// jvmargs
AppendPListArrayToIniFile(infoDictionary, result,
keys[CONFIG_SECTION_JAVAOPTIONS]);
// Generate AppCDS Cache
AppendPListDictionaryToIniFile(infoDictionary, result,
keys[CONFIG_SECTION_APPCDSJAVAOPTIONS]);
AppendPListDictionaryToIniFile(infoDictionary, result,
keys[CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS]);
// args
AppendPListArrayToIniFile(infoDictionary, result,
keys[CONFIG_SECTION_ARGOPTIONS]);
}
return result;
}
TString GetModuleFileNameOSX() {
Dl_info module_info;
if (dladdr(reinterpret_cast<void*> (GetModuleFileNameOSX),
&module_info) == 0) {
// Failed to find the symbol we asked for.
return std::string();
}
return TString(module_info.dli_fname);
}
TString MacPlatform::GetModuleFileName() {
TString result;
DynamicBuffer<TCHAR> buffer(MAX_PATH);
uint32_t size = buffer.GetSize();
if (_NSGetExecutablePath(buffer.GetData(), &size) == 0) {
result = FileSystemStringToString(buffer.GetData());
}
return result;
}
bool MacPlatform::IsMainThread() {
bool result = (pthread_main_np() == 1);
return result;
}
TPlatformNumber MacPlatform::GetMemorySize() {
unsigned long long memory = [[NSProcessInfo processInfo] physicalMemory];
// Convert from bytes to megabytes.
TPlatformNumber result = memory / 1048576;
return result;
}
std::map<TString, TString> MacPlatform::GetKeys() {
std::map<TString, TString> keys;
if (UsePListForConfigFile() == false) {
return Platform::GetKeys();
} else {
keys.insert(std::map<TString, TString>::value_type(CONFIG_VERSION,
_T("app.version")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINJAR_KEY,
_T("JavaMainJarName")));
keys.insert(std::map<TString,
TString>::value_type(CONFIG_MAINMODULE_KEY,
_T("JavaMainModuleName")));
keys.insert(std::map<TString, TString>::value_type(
CONFIG_MAINCLASSNAME_KEY, _T("JavaMainClassName")));
keys.insert(std::map<TString, TString>::value_type(
CONFIG_CLASSPATH_KEY, _T("JavaAppClasspath")));
keys.insert(std::map<TString, TString>::value_type(APP_NAME_KEY,
_T("CFBundleName")));
keys.insert(std::map<TString, TString>::value_type(JAVA_RUNTIME_KEY,
_T("JavaRuntime")));
keys.insert(std::map<TString,
TString>::value_type(JPACKAGE_APP_DATA_DIR,
_T("CFBundleIdentifier")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_SPLASH_KEY,
_T("app.splash")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_MEMORY,
_T("app.memory")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_DEBUG,
_T("app.debug")));
keys.insert(std::map<TString, TString>::value_type(
CONFIG_APPLICATION_INSTANCE, _T("app.application.instance")));
keys.insert(std::map<TString, TString>::value_type(
CONFIG_SECTION_APPLICATION, _T("Application")));
keys.insert(std::map<TString, TString>::value_type(
CONFIG_SECTION_JAVAOPTIONS, _T("JavaOptions")));
keys.insert(std::map<TString, TString>::value_type(
CONFIG_SECTION_APPCDSJAVAOPTIONS, _T("AppCDSJavaOptions")));
keys.insert(std::map<TString, TString>::value_type(
CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS,
_T("AppCDSGenerateCacheJavaOptions")));
keys.insert(std::map<TString, TString>::value_type(
CONFIG_SECTION_ARGOPTIONS, _T("ArgOptions")));
}
return keys;
}

View File

@ -1,112 +0,0 @@
/*
* Copyright (c) 2019, 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.
*/
#ifndef PLATFORM_DEFS_H
#define PLATFORM_DEFS_H
#include <errno.h>
#include <unistd.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include <libgen.h>
#include <string>
using namespace std;
#ifndef MAC
#define MAC
#endif
#define _T(x) x
typedef char TCHAR;
typedef std::string TString;
#define StringLength strlen
typedef unsigned long DWORD;
#define TRAILING_PATHSEPARATOR '/'
#define BAD_TRAILING_PATHSEPARATOR '\\'
#define PATH_SEPARATOR ':'
#define BAD_PATH_SEPARATOR ';'
#define MAX_PATH 1000
typedef long TPlatformNumber;
typedef pid_t TProcessID;
#define HMODULE void*
typedef void* Module;
typedef void* Procedure;
// StringToFileSystemString is a stack object. It's usage is
// simply inline to convert a
// TString to a file system string. Example:
//
// return dlopen(StringToFileSystemString(FileName), RTLD_LAZY);
//
class StringToFileSystemString {
// Prohibit Heap-Based StringToFileSystemString
private:
static void *operator new(size_t size);
static void operator delete(void *ptr);
private:
TCHAR* FData;
bool FRelease;
public:
StringToFileSystemString(const TString &value);
~StringToFileSystemString();
operator TCHAR* ();
};
// FileSystemStringToString is a stack object. It's usage is
// simply inline to convert a
// file system string to a TString. Example:
//
// DynamicBuffer<TCHAR> buffer(MAX_PATH);
// if (readlink("/proc/self/exe", buffer.GetData(), MAX_PATH) != -1)
// result = FileSystemStringToString(buffer.GetData());
//
class FileSystemStringToString {
// Prohibit Heap-Based FileSystemStringToString
private:
static void *operator new(size_t size);
static void operator delete(void *ptr);
private:
TString FData;
public:
FileSystemStringToString(const TCHAR* value);
operator TString ();
};
#endif // PLATFORM_DEFS_H

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -120,12 +120,11 @@ public abstract class AbstractAppImageBuilder {
// legacy way and the main class string must be // legacy way and the main class string must be
// of the format com/foo/Main // of the format com/foo/Main
if (mainJar != null) { if (mainJar != null) {
out.println("app.mainjar=" + getCfgAppDir() out.println("app.classpath=" + getCfgAppDir()
+ mainJar.toPath().getFileName().toString()); + mainJar.toPath().getFileName().toString());
} }
if (mainClass != null) { if (mainClass != null) {
out.println("app.mainclass=" out.println("app.mainclass=" + mainClass);
+ mainClass.replace("\\", "/"));
} }
} }
@ -133,26 +132,20 @@ public abstract class AbstractAppImageBuilder {
out.println("[JavaOptions]"); out.println("[JavaOptions]");
List<String> jvmargs = JAVA_OPTIONS.fetchFrom(params); List<String> jvmargs = JAVA_OPTIONS.fetchFrom(params);
for (String arg : jvmargs) { for (String arg : jvmargs) {
out.println(arg); out.println("java-options=" + arg);
} }
Path modsDir = getAppModsDir(); Path modsDir = getAppModsDir();
if (modsDir != null && modsDir.toFile().exists()) { if (modsDir != null && modsDir.toFile().exists()) {
out.println("--module-path"); out.println("java-options=" + "--module-path");
out.println(getCfgAppDir().replace("\\","/") + "mods"); out.println("java-options=" + getCfgAppDir().replace("\\","/") + "mods");
} }
out.println(); out.println();
out.println("[ArgOptions]"); out.println("[ArgOptions]");
List<String> args = ARGUMENTS.fetchFrom(params); List<String> args = ARGUMENTS.fetchFrom(params);
for (String arg : args) { for (String arg : args) {
if (arg.endsWith("=") && out.println("arguments=" + arg);
(arg.indexOf("=") == arg.lastIndexOf("="))) {
out.print(arg.substring(0, arg.length() - 1));
out.println("\\=");
} else {
out.println(arg);
}
} }
} }
} }

View File

@ -0,0 +1,283 @@
/*
* Copyright (c) 2020, 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 <algorithm>
#include "AppLauncher.h"
#include "JvmLauncher.h"
#include "CfgFile.h"
#include "Log.h"
#include "Dll.h"
#include "Toolbox.h"
#include "SysInfo.h"
#include "FileUtils.h"
AppLauncher::AppLauncher() {
launcherPath = SysInfo::getProcessModulePath();
args = SysInfo::getCommandArgs();
}
namespace {
struct find_jvmlib {
find_jvmlib(const tstring& v): runtimePath(v) {
}
bool operator () (const tstring& jvmLibName) const {
const tstring path = FileUtils::mkpath() << runtimePath << jvmLibName;
return FileUtils::isFileExists(path);
}
private:
const tstring& runtimePath;
};
tstring findJvmLib(const CfgFile& cfgFile, const tstring& defaultRuntimePath,
const tstring_array& jvmLibNames) {
const CfgFile::Properties& appOptions = cfgFile.getProperties(
SectionName::Application);
const CfgFile::Properties::const_iterator runtimePathProp = appOptions.find(
PropertyName::runtime);
tstring runtimePath;
if (runtimePathProp != appOptions.end()) {
runtimePath = CfgFile::asString(*runtimePathProp);
} else {
runtimePath = defaultRuntimePath;
LOG_TRACE(tstrings::any()
<< "Property \"" << PropertyName::runtime.name()
<< "\" not found in \"" << SectionName::Application.name()
<< "\" section of launcher config file."
<< " Using Java runtime from \""
<< runtimePath << "\" directory");
}
const tstring_array::const_iterator jvmLibNameEntry = std::find_if(
jvmLibNames.begin(),
jvmLibNames.end(),
find_jvmlib(runtimePath));
if (jvmLibNameEntry == jvmLibNames.end()) {
JP_THROW(tstrings::any() << "Failed to find JVM in \""
<< runtimePath
<< "\" directory.");
}
return FileUtils::mkpath() << runtimePath << *jvmLibNameEntry;
}
} // namespace
Jvm* AppLauncher::createJvmLauncher() const {
const tstring cfgFilePath = FileUtils::mkpath()
<< appDirPath
<< FileUtils::basename(FileUtils::replaceSuffix(
launcherPath, _T(".cfg")));
LOG_TRACE(tstrings::any() << "Launcher config file path: \""
<< cfgFilePath << "\"");
CfgFile::Macros macros;
macros[_T("$APPDIR")] = appDirPath;
macros[_T("$BINDIR")] = FileUtils::dirname(launcherPath);
macros[_T("$ROOTDIR")] = imageRoot;
CfgFile cfgFile = CfgFile::load(cfgFilePath).expandMacros(macros);
if (!args.empty()) {
// Override default launcher arguments.
cfgFile.setPropertyValue(SectionName::ArgOptions,
PropertyName::arguments, args);
}
std::unique_ptr<Jvm> jvm(new Jvm());
(*jvm)
.setPath(findJvmLib(cfgFile, defaultRuntimePath, jvmLibNames))
.addArgument(launcherPath)
.initFromConfigFile(cfgFile);
return jvm.release();
}
void AppLauncher::launch() const {
std::unique_ptr<Jvm>(createJvmLauncher())->launch();
}
namespace {
const std::string* theLastErrorMsg = 0;
NopLogAppender nopLogAppender;
class StandardLogAppender : public LogAppender {
public:
virtual void append(const LogEvent& v) {
std::cerr << "[" << v.logLevel << "] "
<< v.fileName
<< ":" << v.lineNum
<< ": " << v.message
<< std::endl;
}
} standardLogAppender;
class LastErrorLogAppender : public LogAppender {
public:
virtual void append(const LogEvent& v) {
std::cerr << AppLauncher::lastErrorMsg() << std::endl;
}
} lastErrorLogAppender;
} // namespace
LogAppender& AppLauncher::defaultLastErrorLogAppender() {
return lastErrorLogAppender;
}
std::string AppLauncher::lastErrorMsg() {
if (theLastErrorMsg) {
return *theLastErrorMsg;
}
return "";
}
bool AppLauncher::isWithLogging() {
// If JPACKAGE_DEBUG environment variable is set to "true"
// logging is enabled.
return SysInfo::getEnvVariable(
std::nothrow, _T("JPACKAGE_DEBUG")) == _T("true");
}
namespace {
class ResetLastErrorMsgAtEndOfScope {
public:
~ResetLastErrorMsgAtEndOfScope() {
JP_NO_THROW(theLastErrorMsg = 0);
}
};
class SetLoggerAtEndOfScope {
public:
SetLoggerAtEndOfScope(
std::unique_ptr<WithExtraLogAppender>& withLogAppender,
LogAppender* lastErrorLogAppender):
withLogAppender(withLogAppender),
lastErrorLogAppender(lastErrorLogAppender) {
}
~SetLoggerAtEndOfScope() {
JP_TRY;
std::unique_ptr<WithExtraLogAppender> other(
new WithExtraLogAppender(*lastErrorLogAppender));
withLogAppender.swap(other);
JP_CATCH_ALL;
}
private:
std::unique_ptr<WithExtraLogAppender>& withLogAppender;
LogAppender* lastErrorLogAppender;
};
} // namespace
int AppLauncher::launch(const std::nothrow_t&,
LauncherFunc func, LogAppender* lastErrorLogAppender) {
if (isWithLogging()) {
Logger::defaultLogger().setAppender(standardLogAppender);
} else {
Logger::defaultLogger().setAppender(nopLogAppender);
}
LOG_TRACE_FUNCTION();
if (!lastErrorLogAppender) {
lastErrorLogAppender = &defaultLastErrorLogAppender();
}
std::unique_ptr<WithExtraLogAppender> withLogAppender;
std::string errorMsg;
const ResetLastErrorMsgAtEndOfScope resetLastErrorMsg;
JP_TRY;
// This will temporary change log appenders of the default logger
// to save log messages in the default and additional log appenders.
// Log appenders config of the default logger will be restored to
// the original state at function exit automatically.
const SetLoggerAtEndOfScope setLogger(withLogAppender, lastErrorLogAppender);
func();
return 0;
// The point of all these redefines is to save the last raw error message in
// 'AppLauncher::theLastErrorMsg' variable.
// By default error messages are saved in exception instances with the details
// of error origin (source file, function name, line number).
// We don't want these details in user error messages. However we still want to
// save full information about the last error in the default log appender.
#undef JP_HANDLE_ERROR
#undef JP_HANDLE_UNKNOWN_ERROR
#undef JP_CATCH_EXCEPTIONS
#define JP_HANDLE_ERROR(e) \
do { \
errorMsg = (tstrings::any() << e.what()).str(); \
theLastErrorMsg = &errorMsg; \
reportError(JP_SOURCE_CODE_POS, e); \
} while(0)
#define JP_HANDLE_UNKNOWN_ERROR \
do { \
errorMsg = "Unknown error"; \
theLastErrorMsg = &errorMsg; \
reportUnknownError(JP_SOURCE_CODE_POS); \
} while(0)
#define JP_CATCH_EXCEPTIONS \
catch (const JpErrorBase& e) { \
errorMsg = (tstrings::any() << e.rawMessage()).str(); \
theLastErrorMsg = &errorMsg; \
try { \
throw; \
} catch (const std::runtime_error& e) { \
reportError(JP_SOURCE_CODE_POS, e); \
} \
} catch (const std::runtime_error& e) { \
errorMsg = lastCRTError(); \
theLastErrorMsg = &errorMsg; \
reportError(JP_SOURCE_CODE_POS, e); \
} \
JP_CATCH_UNKNOWN_EXCEPTION
JP_CATCH_ALL;
#undef JP_HANDLE_ERROR
#undef JP_HANDLE_UNKNOWN_ERROR
#undef JP_CATCH_EXCEPTIONS
#define JP_HANDLE_ERROR(e) JP_REPORT_ERROR(e)
#define JP_HANDLE_UNKNOWN_ERROR JP_REPORT_UNKNOWN_ERROR
#define JP_CATCH_EXCEPTIONS JP_DEFAULT_CATCH_EXCEPTIONS
return 1;
}

View File

@ -0,0 +1,83 @@
/*
* Copyright (c) 2020, 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.
*/
#ifndef AppLauncher_h
#define AppLauncher_h
#include "tstrings.h"
class Jvm;
class LogAppender;
class AppLauncher {
public:
AppLauncher();
AppLauncher& setImageRoot(const tstring& v) {
imageRoot = v;
return *this;
}
AppLauncher& setDefaultRuntimePath(const tstring& v) {
defaultRuntimePath = v;
return *this;
}
AppLauncher& setAppDir(const tstring& v) {
appDirPath = v;
return *this;
}
AppLauncher& addJvmLibName(const tstring& v) {
jvmLibNames.push_back(v);
return *this;
}
Jvm* createJvmLauncher() const;
void launch() const;
static LogAppender& defaultLastErrorLogAppender();
static bool isWithLogging();
typedef void (*LauncherFunc) ();
static int launch(const std::nothrow_t&, LauncherFunc func,
LogAppender* lastErrorLogAppender = 0);
static std::string lastErrorMsg();
private:
tstring_array args;
tstring launcherPath;
tstring defaultRuntimePath;
tstring appDirPath;
tstring imageRoot;
tstring_array jvmLibNames;
};
#endif // AppLauncher_h

View File

@ -0,0 +1,295 @@
/*
* Copyright (c) 2020, 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 "kludge_c++11.h"
#include <fstream>
#include <algorithm>
#include "CfgFile.h"
#include "Log.h"
#include "Toolbox.h"
#include "FileUtils.h"
#include "ErrorHandling.h"
const CfgFile::Properties& CfgFile::getProperties(
const SectionName& sectionName) const {
const PropertyMap::const_iterator entry = data.find(sectionName);
if (entry != data.end()) {
return entry->second;
}
return empty;
}
CfgFile& CfgFile::setPropertyValue(const SectionName& sectionName,
const PropertyName& name, const tstring_array& value) {
PropertyMap::iterator entry = data.find(sectionName);
if (entry != data.end()) {
entry->second[name] = value;
} else {
Properties props;
props[name] = value;
data[sectionName] = props;
}
return *this;
}
namespace {
tstring expandMacros(const tstring& str, const CfgFile::Macros& macros) {
tstring reply = str;
CfgFile::Macros::const_iterator it = macros.begin();
const CfgFile::Macros::const_iterator end = macros.end();
for (; it != end; ++it) {
reply = tstrings::replace(reply, it->first, it->second);
}
return reply;
}
} // namespace
CfgFile CfgFile::expandMacros(const Macros& macros) const {
CfgFile copyCfgFile = *this;
PropertyMap::iterator mapIt = copyCfgFile.data.begin();
const PropertyMap::iterator mapEnd = copyCfgFile.data.end();
for (; mapIt != mapEnd; ++mapIt) {
Properties::iterator propertyIt = mapIt->second.begin();
const Properties::iterator propertyEnd = mapIt->second.end();
for (; propertyIt != propertyEnd; ++propertyIt) {
tstring_array::iterator strIt = propertyIt->second.begin();
const tstring_array::iterator strEnd = propertyIt->second.end();
for (; strIt != strEnd; ++strIt) {
tstring newValue;
while ((newValue = ::expandMacros(*strIt, macros)) != *strIt) {
strIt->swap(newValue);
}
}
}
}
return copyCfgFile;
}
namespace {
const CfgFile::SectionName* getSectionName(const tstring& str);
const CfgFile::PropertyName* getPropertyName(const tstring& str);
const CfgFile::SectionName UnknownSection = CfgFile::SectionName(_T(""));
class PurgeSection {
public:
PurgeSection(CfgFile::SectionName& sectionName,
CfgFile::Properties& sectionData,
CfgFile::PropertyMap& cfgFileData):
sectionName(sectionName), sectionData(sectionData),
cfgFileData(cfgFileData) {
}
void operator ()() {
if (sectionName != UnknownSection && !sectionData.empty()) {
std::swap(cfgFileData[sectionName], sectionData);
sectionName = UnknownSection;
sectionData.clear();
}
}
private:
CfgFile::SectionName& sectionName;
CfgFile::Properties& sectionData;
CfgFile::PropertyMap& cfgFileData;
};
class AddProperty {
public:
AddProperty(const CfgFile::SectionName& sectionName,
CfgFile::Properties& sectionData): sectionName(sectionName),
sectionData(sectionData) {
}
void operator ()(const tstring& name, const tstring& value) {
if (sectionName != UnknownSection) {
const CfgFile::PropertyName *known = getPropertyName(name);
if (known) {
sectionData[*known].push_back(value);
}
}
}
private:
const CfgFile::SectionName& sectionName;
CfgFile::Properties& sectionData;
};
} // namepsace
CfgFile CfgFile::load(const tstring& path) {
std::ifstream input(path.c_str());
if (!input.good()) {
JP_THROW(tstrings::any() << "Error opening \"" << path << "\" file: "
<< lastCRTError());
}
CfgFile cfgFile;
SectionName sectionName = UnknownSection;
Properties sectionData;
PurgeSection purgeSection(sectionName, sectionData, cfgFile.data);
AddProperty addProperty(sectionName, sectionData);
std::string utf8line;
int lineno = 0;
while (std::getline(input, utf8line)) {
++lineno;
const tstring line = tstrings::any(utf8line).tstr();
if (line.empty() || _T(';') == *line.begin()) {
// Empty line or comment, ignore.
continue;
}
if (_T('[') == *line.begin()) {
const size_t endIdx = line.find_last_of(_T(']'));
if (endIdx == tstring::npos) {
JP_THROW(tstrings::any() << "Error parsing [" << path
<< "] file at " << lineno << ": Missing ']' character");
}
purgeSection();
// Section begin.
const SectionName *knownName = getSectionName(line.substr(1, endIdx - 1));
if (knownName) {
sectionName = *knownName;
} else {
sectionName = UnknownSection;
}
continue;
}
size_t sepIdx = 0;
do {
sepIdx = line.find_first_of(_T('='), sepIdx);
if (sepIdx == tstring::npos) {
addProperty(line, tstring());
break;
}
if (sepIdx != 0 && line[sepIdx - 1] == '\\') {
sepIdx++;
continue;
}
addProperty(line.substr(0, sepIdx), line.substr(sepIdx + 1));
break;
} while (true);
}
if (!input.eof()) {
// Failed to process file up to the end.
JP_THROW(tstrings::any() << "Failed to read \"" << path
<< "\" file up to the end: " << lastCRTError());
}
purgeSection();
return cfgFile;
}
tstring join(const tstring_array& values, const tstring::value_type delimiter) {
return tstrings::join(values.begin(), values.end(), tstring(1, delimiter));
}
tstring CfgFile::asString(Properties::const_reference property) {
return *property.second.rbegin();
}
tstring CfgFile::asPathList(Properties::const_reference property) {
return join(property.second, FileUtils::pathSeparator);
}
#define JP_ALL_SECTIONS \
JP_SECTION(Application); \
JP_SECTION(JavaOptions); \
JP_SECTION(AppCDSJavaOptions); \
JP_SECTION(AppCDSGenerateCacheJavaOptions); \
JP_SECTION(ArgOptions);
namespace SectionName {
#define JP_SECTION(name) const CfgFile::SectionName name(_T(#name))
JP_ALL_SECTIONS
#undef JP_SECTION
} // namespace SectionName
namespace {
const CfgFile::SectionName* getSectionName(const tstring& str) {
#define JP_SECTION(name) while (str == _T(#name)) { return &SectionName::name; }
JP_ALL_SECTIONS
#undef JP_SECTION
return 0;
}
}
#undef JP_ALL_SECTIONS
#define JP_ALL_PROPERTIES \
JP_PROPERTY(version, "app.version"); \
JP_PROPERTY(mainjar, "app.mainjar"); \
JP_PROPERTY(mainmodule, "app.mainmodule"); \
JP_PROPERTY(mainclass, "app.mainclass"); \
JP_PROPERTY(classpath, "app.classpath"); \
JP_PROPERTY(modulepath, "app.modulepath"); \
JP_PROPERTY(runtime, "app.runtime"); \
JP_PROPERTY(splash, "app.splash"); \
JP_PROPERTY(memory, "app.memory"); \
JP_PROPERTY(arguments, "arguments"); \
JP_PROPERTY(javaOptions, "java-options"); \
namespace PropertyName {
#define JP_PROPERTY(varName, name) const CfgFile::PropertyName varName(_T(name))
JP_ALL_PROPERTIES
#undef JP_PROPERTY
} // namespace PropertyName
namespace {
const CfgFile::PropertyName* getPropertyName(const tstring& str) {
#define JP_PROPERTY(varName, name) while (str == _T(name)) { return &PropertyName::varName; }
JP_ALL_PROPERTIES
#undef JP_PROPERTY
return 0;
}
} // namespace
#undef JP_ALL_PROPERTIES

View File

@ -0,0 +1,131 @@
/*
* Copyright (c) 2020, 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.
*/
#ifndef CfgFile_h
#define CfgFile_h
#include <map>
#include "tstrings.h"
class CfgFile {
public:
template <class Tag> class Id {
public:
Id(const tstring::const_pointer str) : str(str) {
}
bool operator == (const Id& other) const {
return tstring(str) == tstring(other.str);
}
bool operator != (const Id& other) const {
return !operator == (other);
}
bool operator < (const Id& other) const {
return tstring(str) < tstring(other.str);
}
tstring name() const {
return tstring(str);
}
private:
tstring::const_pointer str;
};
class PropertyNameTag {};
typedef Id<PropertyNameTag> PropertyName;
class SectionNameTag {};
typedef Id<SectionNameTag> SectionName;
typedef std::map<PropertyName, tstring_array> Properties;
/**
* Returns properties of the given section.
*/
const Properties& getProperties(const SectionName& sectionName) const;
/**
* Sets new value of the given property in the given section.
*/
CfgFile& setPropertyValue(const SectionName& sectionName,
const PropertyName& name, const tstring& value) {
tstring_array ctnr;
ctnr.push_back(value);
return setPropertyValue(sectionName, name, ctnr);
}
CfgFile& setPropertyValue(const SectionName& sectionName,
const PropertyName& name, const tstring_array& value);
typedef std::map<tstring, tstring> Macros;
/**
* Returns copy of this instance with the given macros expanded.
*/
CfgFile expandMacros(const Macros& macros) const;
static CfgFile load(const tstring& path);
static tstring asString(Properties::const_reference property);
static tstring asPathList(Properties::const_reference property);
typedef std::map<SectionName, Properties> PropertyMap;
private:
PropertyMap data;
Properties empty;
};
namespace SectionName {
extern const CfgFile::SectionName Application;
extern const CfgFile::SectionName JavaOptions;
extern const CfgFile::SectionName AppCDSJavaOptions;
extern const CfgFile::SectionName AppCDSGenerateCacheJavaOptions;
extern const CfgFile::SectionName ArgOptions;
} // namespace SectionName
namespace PropertyName {
extern const CfgFile::PropertyName version;
extern const CfgFile::PropertyName mainjar;
extern const CfgFile::PropertyName mainmodule;
extern const CfgFile::PropertyName mainclass;
extern const CfgFile::PropertyName classpath;
extern const CfgFile::PropertyName modulepath;
extern const CfgFile::PropertyName runtime;
extern const CfgFile::PropertyName splash;
extern const CfgFile::PropertyName memory;
extern const CfgFile::PropertyName arguments;
extern const CfgFile::PropertyName javaOptions;
} // namespace AppPropertyName
#endif // CfgFile_h

View File

@ -0,0 +1,195 @@
/*
* Copyright (c) 2020, 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 <cstring>
#include <jni.h>
#include "JvmLauncher.h"
#include "Log.h"
#include "Dll.h"
#include "CfgFile.h"
#include "FileUtils.h"
#include "Toolbox.h"
#include "ErrorHandling.h"
Jvm& Jvm::initFromConfigFile(const CfgFile& cfgFile) {
const CfgFile::Properties& appOptions = cfgFile.getProperties(
SectionName::Application);
do {
const CfgFile::Properties::const_iterator modulepath = appOptions.find(
PropertyName::modulepath);
if (modulepath != appOptions.end()) {
tstring_array::const_iterator it = modulepath->second.begin();
const tstring_array::const_iterator end = modulepath->second.end();
for (; it != end; ++it) {
addArgument(_T("--module-path"));
addArgument(*it);
};
}
} while (0);
do {
const CfgFile::Properties::const_iterator classpath = appOptions.find(
PropertyName::classpath);
if (classpath != appOptions.end()) {
addArgument(_T("-classpath"));
addArgument(CfgFile::asPathList(*classpath));
}
} while (0);
do {
const CfgFile::Properties::const_iterator splash = appOptions.find(
PropertyName::splash);
if (splash != appOptions.end()) {
const tstring splashPath = CfgFile::asString(*splash);
if (FileUtils::isFileExists(splashPath)) {
addArgument(_T("-splash"));
addArgument(splashPath);
} else {
LOG_WARNING(tstrings::any()
<< "Splash property ignored. File \""
<< splashPath << "\" not found");
}
}
} while (0);
do {
const CfgFile::Properties& section = cfgFile.getProperties(
SectionName::JavaOptions);
const CfgFile::Properties::const_iterator javaOptions = section.find(
PropertyName::javaOptions);
if (javaOptions != section.end()) {
tstring_array::const_iterator it = javaOptions->second.begin();
const tstring_array::const_iterator end = javaOptions->second.end();
for (; it != end; ++it) {
addArgument(*it);
};
}
} while (0);
// No validation of data in config file related to how Java app should be
// launched intentionally.
// Just read what is in config file and put on jvm's command line as is.
do { // Run modular app
const CfgFile::Properties::const_iterator mainmodule = appOptions.find(
PropertyName::mainmodule);
if (mainmodule != appOptions.end()) {
addArgument(_T("-m"));
addArgument(CfgFile::asString(*mainmodule));
}
} while (0);
do { // Run main class
const CfgFile::Properties::const_iterator mainclass = appOptions.find(
PropertyName::mainclass);
if (mainclass != appOptions.end()) {
addArgument(CfgFile::asString(*mainclass));
}
} while (0);
do { // Run jar
const CfgFile::Properties::const_iterator mainjar = appOptions.find(
PropertyName::mainjar);
if (mainjar != appOptions.end()) {
addArgument(_T("-jar"));
addArgument(CfgFile::asString(*mainjar));
}
} while (0);
do {
const CfgFile::Properties& section = cfgFile.getProperties(
SectionName::ArgOptions);
const CfgFile::Properties::const_iterator arguments = section.find(
PropertyName::arguments);
if (arguments != section.end()) {
tstring_array::const_iterator it = arguments->second.begin();
const tstring_array::const_iterator end = arguments->second.end();
for (; it != end; ++it) {
addArgument(*it);
};
}
} while (0);
return *this;
}
namespace {
void convertArgs(const std::vector<std::string>& args, std::vector<char*>& argv) {
argv.reserve(args.size() + 1);
argv.resize(0);
std::vector<std::string>::const_iterator it = args.begin();
const std::vector<std::string>::const_iterator end = args.end();
for (; it != end; ++it) {
argv.push_back(const_cast<char*>(it->c_str()));
};
// Add treminal '0'.
argv.push_back(0);
}
} // namespace
void Jvm::launch() {
typedef int (JNICALL *LaunchFuncType)(int argc, char ** argv,
int jargc, const char** jargv,
int appclassc, const char** appclassv,
const char* fullversion,
const char* dotversion,
const char* pname,
const char* lname,
jboolean javaargs,
jboolean cpwildcard,
jboolean javaw,
jint ergo);
std::vector<char*> argv;
convertArgs(args, argv);
// Don't count terminal '0'.
const int argc = (int)argv.size() - 1;
LOG_TRACE(tstrings::any() << "JVM library: \"" << jvmPath << "\"");
DllFunction<LaunchFuncType> func(Dll(jvmPath), "JLI_Launch");
int exitStatus = func(argc, argv.data(),
0, 0,
0, 0,
"",
"",
"java",
"java",
JNI_FALSE,
JNI_FALSE,
JNI_FALSE,
0);
if (exitStatus != 0) {
JP_THROW("Failed to launch JVM");
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,37 +23,34 @@
* questions. * questions.
*/ */
#ifndef FILEATTRIBUTE_H
#define FILEATTRIBUTE_H
enum FileAttribute { #ifndef JvmLauncher_h
faBlockSpecial, #define JvmLauncher_h
faCharacterSpecial,
faFIFOSpecial,
faNormal,
faDirectory,
faSymbolicLink,
faSocket,
// Owner #include "tstrings.h"
faReadOnly,
faWriteOnly,
faReadWrite,
faExecute,
// Group class CfgFile;
faGroupReadOnly,
faGroupWriteOnly,
faGroupReadWrite,
faGroupExecute,
// Others
faOthersReadOnly,
faOthersWriteOnly,
faOthersReadWrite,
faOthersExecute,
faHidden class Jvm {
public:
Jvm& initFromConfigFile(const CfgFile& cfgFile);
Jvm& addArgument(const tstring& value) {
args.push_back(tstrings::any(value).str());
return *this;
}
Jvm& setPath(const tstring& v) {
jvmPath = v;
return *this;
}
void launch();
private:
tstring jvmPath;
std::vector<std::string> args;
}; };
#endif // FILEATTRIBUTE_H #endif // JvmLauncher_h

View File

@ -0,0 +1,170 @@
/*
* Copyright (c) 2020, 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.
*/
#ifndef __DLL_H_INCLUDED_
#define __DLL_H_INCLUDED_
#ifdef _WIN32
#include <windows.h>
#else
typedef void* HMODULE;
#endif
#include "kludge_c++11.h"
#include <memory>
#include "tstrings.h"
#include "ErrorHandling.h"
//
// Helper classes to dynamically load DLLs and call the libraries functions.
//
/**
* Library loader.
* Usage:
* - load a library specified by full path:
* DLL deployLib(FileUtils::combinePath(javaHome, _T("bin\\deploy.dll"));
*
* Note: library should be specified by full path (due security reasons)
*
* - load system library (DLLs from Windows/System32 (SysWow64) directory):
* DLL kernel32Lib("kernel32", Dll::System());
*/
class Dll {
public:
struct System {};
explicit Dll(const tstrings::any &libPath);
explicit Dll(const tstrings::any &libName, const System &tag);
Dll(const Dll& other);
template <class T>
void getFunction(const tstrings::any &name, T& addr) const {
addr = reinterpret_cast<T>(getFunction(name.str(), true));
}
// returns false & sets addr to NULL if the function not found
template <class T>
bool getFunction(const tstrings::any &name, T& addr, const std::nothrow_t &) const {
addr = reinterpret_cast<T>(getFunction(name.str(), false));
return addr != NULL;
}
const tstring& path() const {
return thePath;
}
HMODULE getHandle() const {
return handle.get();
}
static void freeLibrary(HMODULE h);
struct LibraryReleaser {
typedef HMODULE pointer;
void operator()(HMODULE h) {
freeLibrary(h);
}
};
typedef std::unique_ptr<HMODULE, LibraryReleaser> Handle;
private:
void* getFunction(const std::string &name, bool throwIfNotFound) const;
tstring thePath;
Handle handle;
};
/**
* DllFunction template class helps to check is a library function available and call it.
* Usage example:
* // RegDeleteKeyExW function (from advapi32.dll) is available on Vista+ or on WinXP 64bit
* // so to avoid dependency on the OS version we have to check if it's available at runtime
*
* // the function definition
* typedef LONG (WINAPI *RegDeleteKeyExWFunc)(HKEY hKey, const wchar_t* lpSubKey, REGSAM samDesired, DWORD Reserved);
*
* DllFunction<RegDeleteKeyExWFunc> _RegDeleteKeyExW(Dll("advapi32", Dll::System()), "RegDeleteKeyExW");
* if (_RegDeleteKeyExW.available()) {
* // the function is available, call it
* LONG result = _RegDeleteKeyExW(hKey, subkeyName, samDesired, 0);
* } else {
* // the function is not available, handle this
* throw std::exception("RegDeleteKeyExW function is not available");
* }
*
* // or we can just try to call the function.
* // if the function is not available, exception with the corresponding description is thrown
* DllFunction<RegDeleteKeyExWFunc> _RegDeleteKeyExW(Dll("advapi32", Dll::System()), "RegDeleteKeyExW");
* LONG result = _RegDeleteKeyExW(hKey, subkeyName, samDesired, 0);
*/
template<class funcType>
class DllFunction {
public:
DllFunction(const Dll& library, const tstrings::any &funcName)
: lib(library), theName(funcName.str()) {
lib.getFunction(funcName, funcPtr);
}
DllFunction(const std::nothrow_t&, const Dll& library,
const tstrings::any &funcName)
: lib(library), theName(funcName.str()) {
lib.getFunction(funcName, funcPtr, std::nothrow);
}
bool available() const {
return funcPtr != NULL;
}
std::string name() const {
return theName;
}
const tstring& libPath() const {
return lib.path();
}
operator funcType() const {
if (!available()) {
JP_THROW(tstrings::any() << theName
<< "() function is not available in "
<< lib.path());
}
return funcPtr;
}
private:
const Dll lib;
funcType funcPtr;
std::string theName;
};
#endif // __DLL_H_INCLUDED_

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,8 @@
*/ */
#include <algorithm> #include <algorithm>
#include <string.h>
#include <cerrno>
#include "ErrorHandling.h" #include "ErrorHandling.h"
#include "Log.h" #include "Log.h"
@ -47,7 +49,7 @@ void reportError(const SourceCodePos& pos, const tstring& msg) {
} // namespace } // namespace
void reportError(const SourceCodePos& pos, const std::exception& e) { void reportError(const SourceCodePos& pos, const std::runtime_error& e) {
reportError(pos, (tstrings::any() << "Exception with message \'" reportError(pos, (tstrings::any() << "Exception with message \'"
<< e.what() << "\' caught").tstr()); << e.what() << "\' caught").tstr());
} }
@ -58,7 +60,7 @@ void reportUnknownError(const SourceCodePos& pos) {
} }
std::string makeMessage(const std::exception& e, const SourceCodePos& pos) { std::string makeMessage(const std::runtime_error& e, const SourceCodePos& pos) {
std::ostringstream printer; std::ostringstream printer;
printer << getFilename(pos) << "(" << pos.lno << ") at " printer << getFilename(pos) << "(" << pos.lno << ") at "
<< pos.func << "(): " << pos.func << "(): "
@ -139,3 +141,16 @@ std::string joinErrorMessages(const std::string& a, const std::string& b) {
} }
return str; return str;
} }
std::string lastCRTError() {
#ifndef _WIN32
return strerror(errno);
#else
TCHAR buffer[2048];
if (0 == _tcserror_s(buffer, errno)) {
return (tstrings::any() << buffer).str();
}
return "";
#endif
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -50,18 +50,26 @@
// Logs std::exception caught at 'pos'. // Logs std::exception caught at 'pos'.
void reportError(const SourceCodePos& pos, const std::exception& e); void reportError(const SourceCodePos& pos, const std::runtime_error& e);
// Logs unknown exception caught at 'pos'. // Logs unknown exception caught at 'pos'.
// Assumed to be called from catch (...) {} // Assumed to be called from catch (...) {}
void reportUnknownError(const SourceCodePos& pos); void reportUnknownError(const SourceCodePos& pos);
std::string makeMessage(const std::exception& e, const SourceCodePos& pos); std::string makeMessage(const std::runtime_error& e, const SourceCodePos& pos);
std::string joinErrorMessages(const std::string& a, const std::string& b); std::string joinErrorMessages(const std::string& a, const std::string& b);
std::string lastCRTError();
class JpErrorBase {
public:
virtual const char* rawMessage() const throw() = 0;
};
template <class Base> template <class Base>
class JpError: public Base { class JpError: public JpErrorBase, public Base {
public: public:
JpError(const Base& e, const SourceCodePos& pos): JpError(const Base& e, const SourceCodePos& pos):
Base(e), msg(::makeMessage(e, pos)) { Base(e), msg(::makeMessage(e, pos)) {
@ -74,10 +82,15 @@ public:
const char* what() const throw() { const char* what() const throw() {
return msg.c_str(); return msg.c_str();
} }
// override JpErrorBase
const char* rawMessage() const throw() {
return Base::what();
}
private: private:
// Assert Base is derived from std::exception // Assert Base is derived from std::runtime_error
enum { isDerivedFromStdException = enum { isDerivedFromStdException =
sizeof(static_cast<std::exception*>((Base*)0)) }; sizeof(static_cast<std::runtime_error*>((Base*)0)) };
std::string msg; std::string msg;
}; };
@ -129,7 +142,7 @@ inline JpError<std::runtime_error> makeException(
do {} while(0) do {} while(0)
#define JP_CATCH_STD_EXCEPTION \ #define JP_CATCH_STD_EXCEPTION \
catch (const std::exception& e) \ catch (const std::runtime_error& e) \
{ \ { \
JP_HANDLE_ERROR(e); \ JP_HANDLE_ERROR(e); \
} }

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 2020, 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 <memory>
#include <algorithm>
#include "FileUtils.h"
namespace FileUtils {
#ifdef _WIN32
const tstring::value_type pathSeparator = _T(';');
#else
const tstring::value_type pathSeparator = _T(':');
#endif
namespace {
#ifdef _WIN32
const tstring::value_type dirSeparator = _T('\\');
const tstring::value_type alianDirSeparator = _T('/');
#else
const tstring::value_type dirSeparator = _T('/');
const tstring::value_type alianDirSeparator = _T('\\');
#endif
} // namespace
bool isDirSeparator(const tstring::value_type c) {
return (c == dirSeparator || c == alianDirSeparator);
}
tstring dirname(const tstring &path) {
tstring::size_type pos = path.find_last_of(_T("\\/"));
if (pos != tstring::npos) {
pos = path.find_last_not_of(_T("\\/"), pos); // skip trailing slashes
}
return pos == tstring::npos ? tstring() : path.substr(0, pos + 1);
}
tstring basename(const tstring &path) {
const tstring::size_type pos = path.find_last_of(_T("\\/"));
if (pos == tstring::npos) {
return path;
}
return path.substr(pos + 1);
}
tstring suffix(const tstring &path) {
const tstring::size_type pos = path.rfind(_T('.'));
if (pos == tstring::npos) {
return tstring();
}
const tstring::size_type dirSepPos = path.find_first_of(_T("\\/"),
pos + 1);
if (dirSepPos != tstring::npos) {
return tstring();
}
// test for '/..' and '..' cases
if (pos != 0 && path[pos - 1] == _T('.')
&& (pos == 1 || isDirSeparator(path[pos - 2]))) {
return tstring();
}
return path.substr(pos);
}
tstring combinePath(const tstring& parent, const tstring& child) {
if (parent.empty()) {
return child;
}
if (child.empty()) {
return parent;
}
tstring parentWOSlash = removeTrailingSlash(parent);
// also handle the case when child contains starting slash
bool childHasSlash = isDirSeparator(*child.begin());
tstring childWOSlash = childHasSlash ? child.substr(1) : child;
return parentWOSlash.append(1, dirSeparator).append(childWOSlash);
}
tstring removeTrailingSlash(const tstring& path) {
if (path.empty()) {
return path;
}
tstring::const_reverse_iterator it = path.rbegin();
tstring::const_reverse_iterator end = path.rend();
while (it != end && isDirSeparator(*it)) {
++it;
}
return path.substr(0, end - it);
}
tstring normalizePath(tstring v) {
std::replace(v.begin(), v.end(), alianDirSeparator, dirSeparator);
#ifdef _WIN32
return tstrings::toLower(v);
#else
return v;
#endif
}
tstring replaceSuffix(const tstring& path, const tstring& newSuffix) {
const tstring oldSuffix = suffix(path);
if (oldSuffix.empty()) {
return tstring().append(path).append(newSuffix);
}
return path.substr(0, path.size() - oldSuffix.size()).append(newSuffix);
}
} // namespace FileUtils

View File

@ -0,0 +1,124 @@
/*
* Copyright (c) 2020, 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.
*/
#ifndef FILEUTILS_H
#define FILEUTILS_H
#include <fstream>
#include "SysInfo.h"
namespace FileUtils {
extern const tstring::value_type pathSeparator;
// Returns 'true' if the given character is a path separator.
bool isDirSeparator(const tstring::value_type c);
// returns directory part of the path.
// returns empty string if the path contains only filename.
// if the path ends with slash/backslash,
// returns removeTrailingSlashes(path).
tstring dirname(const tstring &path);
// returns basename part of the path
// if the path ends with slash/backslash, returns empty string.
tstring basename(const tstring &path);
/**
* Translates forward slashes to back slashes and returns lower case version
* of the given string.
*/
tstring normalizePath(tstring v);
// Returns suffix of the path. If the given path has a suffix the first
// character of the return value is '.'.
// Otherwise return value if empty string.
tstring suffix(const tstring &path);
// combines two strings into a path
tstring combinePath(const tstring& parent, const tstring& child);
// removes trailing slashes and backslashes in the path if any
tstring removeTrailingSlash(const tstring& path);
/**
* Replace file suffix, example replaceSuffix("file/path.txt", ".csv")
* @param path file path to replace suffix
* @param suffix new suffix for path
* @return return file path with new suffix
*/
tstring replaceSuffix(const tstring& path, const tstring& suffix=tstring());
/**
* Returns absolute path of the given path.
* If the given string is empty, returns absolute path to the current
* directory.
*/
tstring toAbsolutePath(const tstring& path);
// Helper to construct path from multiple components.
//
// Sample usage:
// Construct "c:\Program Files\Java" string from three components
//
// tstring path = FileUtils::mkpath() << _T("c:")
// << _T("Program Files")
// << _T("Java");
//
class mkpath {
public:
operator const tstring& () const {
return path;
}
mkpath& operator << (const tstring& p) {
path = combinePath(path, p);
return *this;
}
// mimic std::string
const tstring::value_type* c_str() const {
return path.c_str();
}
private:
tstring path;
};
// checks if the file or directory exists
bool isFileExists(const tstring &filePath);
// checks is the specified file is a directory
// returns false if the path does not exist
bool isDirectory(const tstring &filePath);
// checks if the specified directory is not empty
// returns true if the path is an existing directory and
// it contains at least one file other than "." or "..".
bool isDirectoryNotEmpty(const tstring &dirPath);
} // FileUtils
#endif // FILEUTILS_H

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,6 @@
*/ */
#include "Log.h" #include "Log.h"
#include "SysInfo.h"
#include "FileUtils.h" #include "FileUtils.h"
@ -46,12 +45,10 @@ namespace {
// by default log everything // by default log everything
const Logger::LogLevel defaultLogLevel = Logger::LOG_TRACE; const Logger::LogLevel defaultLogLevel = Logger::LOG_TRACE;
char defaultLogAppenderMemory[sizeof(StderrLogAppender)] = {}; char defaultLogAppenderMemory[sizeof(StreamLogAppender)] = {};
char defaultLoggerMemory[sizeof(Logger)] = {}; char defaultLoggerMemory[sizeof(Logger)] = {};
NopLogAppender nopLogApender;
LPCTSTR getLogLevelStr(Logger::LogLevel level) { LPCTSTR getLogLevelStr(Logger::LogLevel level) {
switch (level) { switch (level) {
case Logger::LOG_TRACE: case Logger::LOG_TRACE:
@ -66,26 +63,12 @@ namespace {
return _T("UNKNOWN"); return _T("UNKNOWN");
} }
tstring retrieveModuleName() {
try {
return FileUtils::basename(SysInfo::getCurrentModulePath());
} catch (const std::exception&) {
return _T("Unknown");
}
}
TCHAR moduleName[MAX_PATH] = { 'U', 'n', 'k', 'o', 'w', 'n', TCHAR(0) };
const LPCTSTR format = _T("[%04u/%02u/%02u %02u:%02u:%02u.%03u, %s (PID: %u, TID: %u), %s:%u (%s)]\n\t%s: %s\n");
enum State { NotInitialized, Initializing, Initialized }; enum State { NotInitialized, Initializing, Initialized };
State state = NotInitialized; State state = NotInitialized;
} }
LogEvent::LogEvent() { LogEvent::LogEvent() {
memset(this, 0, sizeof(*this));
moduleName = tstring();
logLevel = tstring(); logLevel = tstring();
fileName = tstring(); fileName = tstring();
funcName = tstring(); funcName = tstring();
@ -93,10 +76,6 @@ LogEvent::LogEvent() {
} }
StderrLogAppender::StderrLogAppender() {
}
/*static*/ /*static*/
Logger& Logger::defaultLogger() { Logger& Logger::defaultLogger() {
Logger* reply = reinterpret_cast<Logger*>(defaultLoggerMemory); Logger* reply = reinterpret_cast<Logger*>(defaultLoggerMemory);
@ -106,27 +85,17 @@ Logger& Logger::defaultLogger() {
// object. OS will do resources clean up anyways when application // object. OS will do resources clean up anyways when application
// terminates and the default log appender should live as long as // terminates and the default log appender should live as long as
// application lives. // application lives.
reply->appender = new (defaultLogAppenderMemory) StderrLogAppender(); reply->appender = new (defaultLogAppenderMemory) StreamLogAppender(
std::cout);
} }
if (Initializing == state) { if (Initializing == state) {
// Recursive call to Logger::defaultLogger. // Recursive call to Logger::defaultLogger.
moduleName[0] = TCHAR(0); initializingLogging();
} else if (NotInitialized == state) { } else if (NotInitialized == state) {
state = Initializing; state = Initializing;
initializeLogging();
tstring mname = retrieveModuleName();
mname.resize(_countof(moduleName) - 1);
std::memcpy(moduleName, mname.c_str(), mname.size());
moduleName[mname.size()] = TCHAR(0);
// if JPACKAGE_DEBUG environment variable is NOT set to "true" disable
// logging.
if (SysInfo::getEnvVariable(std::nothrow,
L"JPACKAGE_DEBUG") != L"true") {
reply->appender = &nopLogApender;
}
state = Initialized; state = Initialized;
} }
@ -152,14 +121,8 @@ bool Logger::isLoggable(LogLevel logLevel) const {
void Logger::log(LogLevel logLevel, LPCTSTR fileName, int lineNum, void Logger::log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
LPCTSTR funcName, const tstring& message) const { LPCTSTR funcName, const tstring& message) const {
LogEvent logEvent; LogEvent logEvent;
LogEvent::init(logEvent);
// [YYYY/MM/DD HH:MM:SS.ms, <module> (PID: processID, TID: threadID),
// fileName:lineNum (funcName)] <tab>LEVEL: message
GetLocalTime(&logEvent.ts);
logEvent.pid = GetCurrentProcessId();
logEvent.tid = GetCurrentThreadId();
logEvent.moduleName = moduleName;
logEvent.fileName = FileUtils::basename(fileName); logEvent.fileName = FileUtils::basename(fileName);
logEvent.funcName = funcName; logEvent.funcName = funcName;
logEvent.logLevel = getLogLevelStr(logLevel); logEvent.logLevel = getLogLevelStr(logLevel);
@ -170,18 +133,20 @@ void Logger::log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
} }
void StderrLogAppender::append(const LogEvent& v) void StreamLogAppender::append(const LogEvent& v) {
{ tstring platformLogStr;
const tstring out = tstrings::unsafe_format(format, LogEvent::appendFormatted(v, platformLogStr);
unsigned(v.ts.wYear), unsigned(v.ts.wMonth), unsigned(v.ts.wDay),
unsigned(v.ts.wHour), unsigned(v.ts.wMinute), unsigned(v.ts.wSecond),
unsigned(v.ts.wMilliseconds),
v.moduleName.c_str(), v.pid, v.tid,
v.fileName.c_str(), v.lineNum, v.funcName.c_str(),
v.logLevel.c_str(),
v.message.c_str());
std::cerr << tstrings::toUtf8(out); tostringstream printer;
printer << _T('[') << platformLogStr
<< v.fileName << _T(':') << v.lineNum
<< _T(" (") << v.funcName << _T(')')
<< _T(']')
<< _T('\n') << _T('\t')
<< v.logLevel << _T(": ")
<< v.message;
*consumer << tstrings::toUtf8(printer.str()) << std::endl;
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,7 @@
#ifndef __LOG_H_INCLUDED_ #ifndef __LOG_H_INCLUDED_
#define __LOG_H_INCLUDED_ #define __LOG_H_INCLUDED_
#include <windows.h> #include "PlatformLogEvent.h"
#include "tstrings.h" #include "tstrings.h"
@ -45,11 +45,10 @@
* (usually value of the TMP env. var) * (usually value of the TMP env. var)
*/ */
struct LogEvent { class Logger;
SYSTEMTIME ts; class StreamLogAppender;
long tid;
long pid; struct LogEvent: public PlatformLogEvent {
tstring moduleName;
tstring logLevel; tstring logLevel;
tstring fileName; tstring fileName;
int lineNum; int lineNum;
@ -57,6 +56,14 @@ struct LogEvent {
tstring message; tstring message;
LogEvent(); LogEvent();
friend class Logger;
friend class StreamLogAppender;
private:
static void init(PlatformLogEvent& logEvent);
static void appendFormatted(const PlatformLogEvent& logEvent,
tstring& buffer);
}; };
@ -96,13 +103,18 @@ private:
/** /**
* Writes log events to stderr. * Writes log events to the given std::ostream.
* Supposed to be used with std::cout or std::cerr
*/ */
class StderrLogAppender: public LogAppender { class StreamLogAppender: public LogAppender {
public: public:
explicit StderrLogAppender(); explicit StreamLogAppender(std::ostream& consumer) : consumer(&consumer) {
}
virtual void append(const LogEvent& v); virtual void append(const LogEvent& v);
private:
std::ostream* consumer;
}; };
@ -154,19 +166,42 @@ public:
private: private:
const Logger &log; const Logger &log;
const LogLevel level; const LogLevel level;
const bool needLog;
const tstring file; const tstring file;
const int line; const int line;
const tstring func; const tstring func;
const tstring scope; const tstring scope;
const bool needLog;
}; };
private:
static void initializingLogging();
static void initializeLogging();
private: private:
LogLevel level; LogLevel level;
LogAppender* appender; LogAppender* appender;
}; };
class WithExtraLogAppender {
public:
WithExtraLogAppender(LogAppender& logAppender):
oldLogAppender(Logger::defaultLogger().getAppender()),
newLogAppender(&Logger::defaultLogger().getAppender(),
&logAppender) {
Logger::defaultLogger().setAppender(newLogAppender);
}
virtual ~WithExtraLogAppender() {
Logger::defaultLogger().setAppender(oldLogAppender);
}
private:
LogAppender& oldLogAppender;
TeeLogAppender newLogAppender;
};
// base logging macro // base logging macro
#define LOGGER_LOG(logger, logLevel, message) \ #define LOGGER_LOG(logger, logLevel, message) \
do { \ do { \

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -47,7 +47,11 @@ struct SourceCodePos
// Initializes SourceCodePos instance with the // Initializes SourceCodePos instance with the
// information from the point of calling. // information from the point of calling.
#define JP_SOURCE_CODE_POS SourceCodePos(__FILE__, __FUNCTION__, __LINE__) #ifdef THIS_FILE
#define JP_SOURCE_CODE_POS SourceCodePos(THIS_FILE, __FUNCTION__, __LINE__)
#else
#define JP_SOURCE_CODE_POS SourceCodePos(__FILE__, __FUNCTION__, __LINE__)
#endif
#endif // #ifndef SourceCodePos_h #endif // #ifndef SourceCodePos_h

View File

@ -0,0 +1,182 @@
/*
* Copyright (c) 2020, 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.
*/
#ifndef Toolbox_h
#define Toolbox_h
#include <algorithm>
#include "tstrings.h"
/**
* Placeholder for API not falling into any particular category.
*/
struct deletePtr {
template <class PtrT>
void operator () (PtrT ptr) const {
delete ptr;
}
};
/**
* Deletes all pointers in the given range of items.
*/
template <class It>
void deleteAll(It b, It e) {
std::for_each(b, e, deletePtr());
}
/**
* Deletes all pointers from the container.
*/
template <class Ctnr>
void deleteAll(Ctnr& ctnr) {
deleteAll(std::begin(ctnr), std::end(ctnr));
}
/**
* Applies std::for_each() to the given object that has begin() and end()
* methods.
*/
template <class Ctnr, class Fn>
void forEach(Ctnr& ctnr, Fn fn) {
std::for_each(std::begin(ctnr), std::end(ctnr), fn);
}
template <class Ctnr, class Fn>
void forEach(const Ctnr& ctnr, Fn fn) {
std::for_each(std::begin(ctnr), std::end(ctnr), fn);
}
/**
* Runs the given functor from destructor. Don't use directly.
* This is just a helper for runAtEndOfScope().
*/
template <class Fn>
class AtEndOfScope {
Fn func;
bool theAbort;
public:
explicit AtEndOfScope(Fn f): func(f), theAbort(false) {
}
~AtEndOfScope() {
if (!theAbort) {
JP_NO_THROW(func());
}
}
void abort(bool v=true) {
theAbort = v;
}
};
/**
* Helper to create AtEndOfScope instance without need to
* specify template type explicitly. Like std::make_pair to construct
* std::pair instance.
*
* Use case:
* Say you need to call a function (foo()) at exit from another
* function (bar()).
* You will normally do:
* void bar() {
* workload();
* foo();
* }
*
* If workload() can throw exceptions things become little bit more
* complicated:
* void bar() {
* JP_NO_THROW(workload());
* foo();
* }
*
* If there is branching in bar() it is little bit more complicated again:
* int bar() {
* if (...) {
* JP_NO_THROW(workload());
* foo();
* return 0;
* }
* if (...) {
* JP_NO_THROW(workload2());
* foo();
* return 1;
* }
* foo();
* return 2;
* }
*
* So for relatively complex bar() this approach will end up with
* missing foo() call. The standard solution to avoid errors like this,
* is to call foo() from some object's destructor, i.e. delegate
* responsibility to ensure it is always called to compiler:
*
* struct FooCaller {
* ~FooCaller() { JP_NO_THROW(foo()); }
* };
*
* int bar() {
* FooCaller fooCaller;
* if (...) {
* JP_NO_THROW(workload());
* return 0;
* }
* if (...) {
* JP_NO_THROW(workload2());
* foo();
* }
* return 2;
* }
*
* However it is annoying to explicitly create FooCaller-like types
* for tasks like this. Use of runAtEndOfScope() saves you from this:
*
* int bar() {
* const auto fooCaller = runAtEndOfScope(foo);
* if (...) {
* JP_NO_THROW(workload());
* return 0;
* }
* if (...) {
* JP_NO_THROW(workload2());
* foo();
* }
* return 2;
* }
*
*/
template <class Fn>
AtEndOfScope<Fn> runAtEndOfScope(Fn func) {
return AtEndOfScope<Fn>(func);
}
#endif // #ifndef Toolbox_h

View File

@ -0,0 +1,170 @@
/*
* Copyright (c) 2020, 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.
*/
#ifndef kludge_cxx11_h
#define kludge_cxx11_h
//
// This file contains kludge implementation of C++11 features needed to build
// jpackage until Open JDK moves forward from C++98 standard.
//
#ifdef __GNUG__
#ifndef __clang__
#if __cplusplus < 201103L
#define JP_WITH_KLUDGE_CXX11
#endif
#endif
#endif
#ifdef JP_WITH_KLUDGE_CXX11
#include <algorithm>
namespace std {
namespace impl {
template <typename Tp, typename Dp>
class unique_ptr_impl {
public:
typedef typename Dp::pointer pointer;
typedef Tp element_type;
typedef Dp deleter_type;
unique_ptr_impl(): value(0) {
}
unique_ptr_impl(pointer p): value(p) {
}
pointer release() {
const pointer retValue = value;
value = 0;
return retValue;
}
void swap(unique_ptr_impl& other) {
std::swap(value, other.value);
}
pointer get() const {
return value;
}
private:
unique_ptr_impl(const unique_ptr_impl&);
unique_ptr_impl& operator= (const unique_ptr_impl&);
private:
pointer value;
};
} // namespace impl
template <typename Tp>
struct default_delete {
typedef Tp* pointer;
void operator()(Tp* ptr) const {
delete ptr;
}
};
template <typename Tp, typename Dp = default_delete<Tp> >
class unique_ptr {
typedef impl::unique_ptr_impl<Tp, Dp> impl_type;
public:
typedef typename impl_type::pointer pointer;
typedef typename impl_type::element_type element_type;
typedef typename impl_type::deleter_type deleter_type;
unique_ptr() {
}
unique_ptr(pointer p): impl(p) {
}
~unique_ptr() {
if (get() != 0) {
impl_type tmp;
tmp.swap(impl);
Dp()(tmp.get());
}
}
pointer release() {
return impl.release();
}
void swap(unique_ptr& other) {
impl.swap(other.impl);
}
pointer get() const {
return impl.get();
}
element_type& operator *() const {
return *impl.get();
}
pointer operator ->() const {
return impl.get();
}
private:
impl_type impl;
};
template <class Ctnr>
typename Ctnr::const_iterator begin(const Ctnr& ctnr) {
return ctnr.begin();
}
template <class Ctnr>
typename Ctnr::iterator begin(Ctnr& ctnr) {
return ctnr.begin();
}
template <class Ctnr>
typename Ctnr::const_iterator end(const Ctnr& ctnr) {
return ctnr.end();
}
template <class Ctnr>
typename Ctnr::iterator end(Ctnr& ctnr) {
return ctnr.end();
}
} // namespace std
#endif // #ifdef JP_WITH_KLUDGE_CXX11
#endif // #ifndef kludge_cxx11_h

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -52,8 +52,15 @@ tstring unsafe_format(tstring::const_pointer format, ...) {
#ifdef _MSC_VER #ifdef _MSC_VER
ret = _vsntprintf_s(&*fmtout.begin(), fmtout.size(), _TRUNCATE, format, args); ret = _vsntprintf_s(&*fmtout.begin(), fmtout.size(), _TRUNCATE, format, args);
#else #else
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
// With g++ this compiles only with '-std=gnu++0x' option // With g++ this compiles only with '-std=gnu++0x' option
ret = vsnprintf(&*fmtout.begin(), fmtout.size(), format, args); ret = vsnprintf(&*fmtout.begin(), fmtout.size(), format, args);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif #endif
} while(-1 == ret); } while(-1 == ret);
va_end(args); va_end(args);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -198,7 +198,7 @@ namespace format_detail {
} }
inline str_arg_value<std::string> arg(std::string::const_pointer v) { inline str_arg_value<std::string> arg(std::string::const_pointer v) {
return (v ? v : "(null)"); return std::string(v ? v: "(null)");
} }
#ifdef TSTRINGS_WITH_WCHAR #ifdef TSTRINGS_WITH_WCHAR
@ -207,7 +207,7 @@ namespace format_detail {
} }
inline str_arg_value<std::wstring> arg(std::wstring::const_pointer v) { inline str_arg_value<std::wstring> arg(std::wstring::const_pointer v) {
return (v ? v : L"(null)"); return std::wstring(v ? v : L"(null)");
} }
#else #else
void arg(const std::wstring&); // Compilation error by design. void arg(const std::wstring&); // Compilation error by design.

View File

@ -1,81 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef FILEPATH_H
#define FILEPATH_H
#include "Platform.h"
#include "PlatformString.h"
#include "FileAttribute.h"
#include <vector>
class FileAttributes {
private:
TString FFileName;
bool FFollowLink;
std::vector<FileAttribute> FAttributes;
bool WriteAttributes();
bool ReadAttributes();
bool Valid(const FileAttribute Value);
public:
FileAttributes(const TString FileName, bool FollowLink = true);
void Append(const FileAttribute Value);
bool Contains(const FileAttribute Value);
void Remove(const FileAttribute Value);
};
class FilePath {
private:
FilePath(void) {}
~FilePath(void) {}
public:
static bool FileExists(const TString FileName);
static bool DirectoryExists(const TString DirectoryName);
static bool DeleteFile(const TString FileName);
static bool DeleteDirectory(const TString DirectoryName);
static TString ExtractFilePath(TString Path);
static TString ExtractFileExt(TString Path);
static TString ExtractFileName(TString Path);
static TString ChangeFileExt(TString Path, TString Extension);
static TString IncludeTrailingSeparator(const TString value);
static TString IncludeTrailingSeparator(const char* value);
static TString IncludeTrailingSeparator(const wchar_t* value);
static TString FixPathForPlatform(TString Path);
static TString FixPathSeparatorForPlatform(TString Path);
static TString PathSeparator();
static bool CreateDirectory(TString Path, bool ownerOnly);
static void ChangePermissions(TString FileName, bool ownerOnly);
};
#endif //FILEPATH_H

View File

@ -1,240 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "Helpers.h"
#include "PlatformString.h"
#include "PropertyFile.h"
bool Helpers::SplitOptionIntoNameValue(
TString option, TString& Name, TString& Value) {
bool hasValue = false;
Name = _T("");
Value = _T("");
unsigned int index = 0;
for (; index < option.length(); index++) {
TCHAR c = option[index];
switch (c) {
case '=': {
index++;
hasValue = true;
break;
}
case '\\': {
if (index + 1 < option.length()) {
c = option[index + 1];
switch (c) {
case '\\': {
index++;
Name += '\\';
break;
}
case '=': {
index++;
Name += '=';
break;
}
}
}
continue;
}
default: {
Name += c;
continue;
}
}
break;
}
if (hasValue) {
Value = option.substr(index, index - option.length());
}
return (option.length() > 0);
}
TString Helpers::ReplaceString(TString subject, const TString& search,
const TString& replace) {
size_t pos = 0;
while((pos = subject.find(search, pos)) != TString::npos) {
subject.replace(pos, search.length(), replace);
pos += replace.length();
}
return subject;
}
TString Helpers::ConvertIdToFilePath(TString Value) {
TString search;
search = '.';
TString replace;
replace = '/';
TString result = ReplaceString(Value, search, replace);
return result;
}
TString Helpers::ConvertIdToJavaPath(TString Value) {
TString search;
search = '.';
TString replace;
replace = '/';
TString result = ReplaceString(Value, search, replace);
search = '\\';
result = ReplaceString(result, search, replace);
return result;
}
TString Helpers::ConvertJavaPathToId(TString Value) {
TString search;
search = '/';
TString replace;
replace = '.';
TString result = ReplaceString(Value, search, replace);
return result;
}
OrderedMap<TString, TString>
Helpers::GetJavaOptionsFromConfig(IPropertyContainer* config) {
OrderedMap<TString, TString> result;
for (unsigned int index = 0; index < config->GetCount(); index++) {
TString argname =
TString(_T("jvmarg.")) + PlatformString(index + 1).toString();
TString argvalue;
if (config->GetValue(argname, argvalue) == false) {
break;
}
else if (argvalue.empty() == false) {
TString name;
TString value;
if (Helpers::SplitOptionIntoNameValue(argvalue, name, value)) {
result.Append(name, value);
}
}
}
return result;
}
std::list<TString> Helpers::GetArgsFromConfig(IPropertyContainer* config) {
std::list<TString> result;
for (unsigned int index = 0; index < config->GetCount(); index++) {
TString argname = TString(_T("arg."))
+ PlatformString(index + 1).toString();
TString argvalue;
if (config->GetValue(argname, argvalue) == false) {
break;
}
else if (argvalue.empty() == false) {
result.push_back((argvalue));
}
}
return result;
}
std::list<TString>
Helpers::MapToNameValueList(OrderedMap<TString, TString> Map) {
std::list<TString> result;
std::vector<TString> keys = Map.GetKeys();
for (OrderedMap<TString, TString>::const_iterator iterator = Map.begin();
iterator != Map.end(); iterator++) {
JPPair<TString, TString> *item = *iterator;
TString key = item->first;
TString value = item->second;
if (value.length() == 0) {
result.push_back(key);
} else {
result.push_back(key + _T('=') + value);
}
}
return result;
}
TString Helpers::NameValueToString(TString name, TString value) {
TString result;
if (value.empty() == true) {
result = name;
}
else {
result = name + TString(_T("=")) + value;
}
return result;
}
std::list<TString> Helpers::StringToArray(TString Value) {
std::list<TString> result;
TString line;
for (unsigned int index = 0; index < Value.length(); index++) {
TCHAR c = Value[index];
switch (c) {
case '\n': {
result.push_back(line);
line = _T("");
break;
}
case '\r': {
result.push_back(line);
line = _T("");
if (Value[index + 1] == '\n')
index++;
break;
}
default: {
line += c;
}
}
}
// The buffer may not have ended with a Carriage Return/Line Feed.
if (line.length() > 0) {
result.push_back(line);
}
return result;
}

View File

@ -1,66 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef HELPERS_H
#define HELPERS_H
#include "Platform.h"
#include "OrderedMap.h"
#include "IniFile.h"
class Helpers {
private:
Helpers(void) {}
~Helpers(void) {}
public:
// Supports two formats for option:
// Example 1:
// foo=bar
//
// Example 2:
// <name=foo=, value=goo>
static bool SplitOptionIntoNameValue(TString option,
TString& Name, TString& Value);
static TString ReplaceString(TString subject, const TString& search,
const TString& replace);
static TString ConvertIdToFilePath(TString Value);
static TString ConvertIdToJavaPath(TString Value);
static TString ConvertJavaPathToId(TString Value);
static OrderedMap<TString, TString>
GetJavaOptionsFromConfig(IPropertyContainer* config);
static std::list<TString> GetArgsFromConfig(IPropertyContainer* config);
static std::list<TString>
MapToNameValueList(OrderedMap<TString, TString> Map);
static TString NameValueToString(TString name, TString value);
static std::list<TString> StringToArray(TString Value);
};
#endif // HELPERS_H

View File

@ -1,261 +0,0 @@
/*
* Copyright (c) 2015, 2019, 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 "IniFile.h"
#include "Helpers.h"
#include <string>
IniFile::IniFile() : ISectionalPropertyContainer() {
}
IniFile::~IniFile() {
for (OrderedMap<TString, IniSectionData*>::iterator iterator =
FMap.begin(); iterator != FMap.end(); iterator++) {
JPPair<TString, IniSectionData*> *item = *iterator;
delete item->second;
}
}
bool IniFile::LoadFromFile(const TString FileName) {
bool result = false;
Platform& platform = Platform::GetInstance();
std::list<TString> contents = platform.LoadFromFile(FileName);
if (contents.empty() == false) {
bool found = false;
// Determine the if file is an INI file or property file.
// Assign FDefaultSection if it is
// an INI file. Otherwise FDefaultSection is NULL.
for (std::list<TString>::const_iterator iterator = contents.begin();
iterator != contents.end(); iterator++) {
TString line = *iterator;
if (line[0] == ';') {
// Semicolon is a comment so ignore the line.
continue;
}
else {
if (line[0] == '[') {
found = true;
}
break;
}
}
if (found == true) {
TString sectionName;
for (std::list<TString>::const_iterator iterator = contents.begin();
iterator != contents.end(); iterator++) {
TString line = *iterator;
if (line[0] == ';') {
// Semicolon is a comment so ignore the line.
continue;
}
else if (line[0] == '[' && line[line.length() - 1] == ']') {
sectionName = line.substr(1, line.size() - 2);
}
else if (sectionName.empty() == false) {
TString name;
TString value;
if (Helpers::SplitOptionIntoNameValue(
line, name, value) == true) {
Append(sectionName, name, value);
}
}
}
result = true;
}
}
return result;
}
bool IniFile::SaveToFile(const TString FileName, bool ownerOnly) {
bool result = false;
std::list<TString> contents;
std::vector<TString> keys = FMap.GetKeys();
for (unsigned int index = 0; index < keys.size(); index++) {
TString name = keys[index];
IniSectionData *section = NULL;
if (FMap.GetValue(name, section) == true && section != NULL) {
contents.push_back(_T("[") + name + _T("]"));
std::list<TString> lines = section->GetLines();
contents.insert(contents.end(), lines.begin(), lines.end());
contents.push_back(_T(""));
}
}
Platform& platform = Platform::GetInstance();
platform.SaveToFile(FileName, contents, ownerOnly);
result = true;
return result;
}
void IniFile::Append(const TString SectionName,
const TString Key, TString Value) {
if (FMap.ContainsKey(SectionName) == true) {
IniSectionData* section = NULL;
if (FMap.GetValue(SectionName, section) == true && section != NULL) {
section->SetValue(Key, Value);
}
}
else {
IniSectionData *section = new IniSectionData();
section->SetValue(Key, Value);
FMap.Append(SectionName, section);
}
}
void IniFile::AppendSection(const TString SectionName,
OrderedMap<TString, TString> Values) {
if (FMap.ContainsKey(SectionName) == true) {
IniSectionData* section = NULL;
if (FMap.GetValue(SectionName, section) == true && section != NULL) {
section->Append(Values);
}
}
else {
IniSectionData *section = new IniSectionData(Values);
FMap.Append(SectionName, section);
}
}
bool IniFile::GetValue(const TString SectionName,
const TString Key, TString& Value) {
bool result = false;
IniSectionData* section = NULL;
if (FMap.GetValue(SectionName, section) == true && section != NULL) {
result = section->GetValue(Key, Value);
}
return result;
}
bool IniFile::SetValue(const TString SectionName,
const TString Key, TString Value) {
bool result = false;
IniSectionData* section = NULL;
if (FMap.GetValue(SectionName, section) && section != NULL) {
result = section->SetValue(Key, Value);
}
else {
Append(SectionName, Key, Value);
}
return result;
}
bool IniFile::GetSection(const TString SectionName,
OrderedMap<TString, TString> &Data) {
bool result = false;
if (FMap.ContainsKey(SectionName) == true) {
IniSectionData* section = NULL;
if (FMap.GetValue(SectionName, section) == true && section != NULL) {
OrderedMap<TString, TString> data = section->GetData();
Data.Append(data);
result = true;
}
}
return result;
}
bool IniFile::ContainsSection(const TString SectionName) {
return FMap.ContainsKey(SectionName);
}
//----------------------------------------------------------------------------
IniSectionData::IniSectionData() {
FMap.SetAllowDuplicates(true);
}
IniSectionData::IniSectionData(OrderedMap<TString, TString> Values) {
FMap = Values;
}
std::vector<TString> IniSectionData::GetKeys() {
return FMap.GetKeys();
}
std::list<TString> IniSectionData::GetLines() {
std::list<TString> result;
std::vector<TString> keys = FMap.GetKeys();
for (unsigned int index = 0; index < keys.size(); index++) {
TString name = keys[index];
TString value;
if (FMap.GetValue(name, value) == true) {
name = Helpers::ReplaceString(name, _T("="), _T("\\="));
value = Helpers::ReplaceString(value, _T("="), _T("\\="));
TString line = name + _T('=') + value;
result.push_back(line);
}
}
return result;
}
OrderedMap<TString, TString> IniSectionData::GetData() {
OrderedMap<TString, TString> result = FMap;
return result;
}
bool IniSectionData::GetValue(const TString Key, TString& Value) {
return FMap.GetValue(Key, Value);
}
bool IniSectionData::SetValue(const TString Key, TString Value) {
return FMap.SetValue(Key, Value);
}
void IniSectionData::Append(OrderedMap<TString, TString> Values) {
FMap.Append(Values);
}
size_t IniSectionData::GetCount() {
return FMap.Count();
}

View File

@ -1,82 +0,0 @@
/*
* Copyright (c) 2015, 2019, 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.
*/
#ifndef INIFILE_H
#define INIFILE_H
#include "Platform.h"
#include "OrderedMap.h"
#include <map>
class IniSectionData : public IPropertyContainer {
private:
OrderedMap<TString, TString> FMap;
public:
IniSectionData();
IniSectionData(OrderedMap<TString, TString> Values);
std::vector<TString> GetKeys();
std::list<TString> GetLines();
OrderedMap<TString, TString> GetData();
bool SetValue(const TString Key, TString Value);
void Append(OrderedMap<TString, TString> Values);
virtual bool GetValue(const TString Key, TString& Value);
virtual size_t GetCount();
};
class IniFile : public ISectionalPropertyContainer {
private:
OrderedMap<TString, IniSectionData*> FMap;
public:
IniFile();
virtual ~IniFile();
void internalTest();
bool LoadFromFile(const TString FileName);
bool SaveToFile(const TString FileName, bool ownerOnly = true);
void Append(const TString SectionName, const TString Key, TString Value);
void AppendSection(const TString SectionName,
OrderedMap<TString, TString> Values);
bool SetValue(const TString SectionName,
const TString Key, TString Value);
// ISectionalPropertyContainer
virtual bool GetSection(const TString SectionName,
OrderedMap<TString, TString> &Data);
virtual bool ContainsSection(const TString SectionName);
virtual bool GetValue(const TString SectionName,
const TString Key, TString& Value);
};
#endif // INIFILE_H

View File

@ -1,318 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "JavaVirtualMachine.h"
#include "Platform.h"
#include "PlatformString.h"
#include "FilePath.h"
#include "Package.h"
#include "Helpers.h"
#include "Messages.h"
#include "Macros.h"
#include "jni.h"
#include <map>
#include <list>
#include <sstream>
bool RunVM() {
JavaVirtualMachine javavm;
bool result = javavm.StartJVM();
if (!result) {
Platform& platform = Platform::GetInstance();
platform.ShowMessage(_T("Failed to launch JVM\n"));
}
return result;
}
//----------------------------------------------------------------------------
JavaOptions::JavaOptions(): FOptions(NULL) {
}
JavaOptions::~JavaOptions() {
if (FOptions != NULL) {
for (unsigned int index = 0; index < GetCount(); index++) {
delete[] FOptions[index].optionString;
}
delete[] FOptions;
}
}
void JavaOptions::AppendValue(const TString Key, TString Value, void* Extra) {
JavaOptionItem item;
item.name = Key;
item.value = Value;
item.extraInfo = Extra;
FItems.push_back(item);
}
void JavaOptions::AppendValue(const TString Key, TString Value) {
AppendValue(Key, Value, NULL);
}
void JavaOptions::AppendValue(const TString Key) {
AppendValue(Key, _T(""), NULL);
}
void JavaOptions::AppendValues(OrderedMap<TString, TString> Values) {
if (Values.GetAllowDuplicates()) {
for (int i = 0; i < (int)Values.Count(); i++) {
TString name, value;
bool bResult = Values.GetKey(i, name);
bResult &= Values.GetValue(i, value);
if (bResult) {
AppendValue(name, value);
}
}
} else { // In case we asked to add values from OrderedMap with allow
// duplicates set to false. Not used now, but should avoid possible
// bugs.
std::vector<TString> orderedKeys = Values.GetKeys();
for (std::vector<TString>::const_iterator iterator = orderedKeys.begin();
iterator != orderedKeys.end(); iterator++) {
TString name = *iterator;
TString value;
if (Values.GetValue(name, value) == true) {
AppendValue(name, value);
}
}
}
}
void JavaOptions::ReplaceValue(const TString Key, TString Value) {
for (std::list<JavaOptionItem>::iterator iterator = FItems.begin();
iterator != FItems.end(); iterator++) {
TString lkey = iterator->name;
if (lkey == Key) {
JavaOptionItem item = *iterator;
item.value = Value;
iterator = FItems.erase(iterator);
FItems.insert(iterator, item);
break;
}
}
}
std::list<TString> JavaOptions::ToList() {
std::list<TString> result;
Macros& macros = Macros::GetInstance();
for (std::list<JavaOptionItem>::const_iterator iterator = FItems.begin();
iterator != FItems.end(); iterator++) {
TString key = iterator->name;
TString value = iterator->value;
TString option = Helpers::NameValueToString(key, value);
option = macros.ExpandMacros(option);
result.push_back(option);
}
return result;
}
size_t JavaOptions::GetCount() {
return FItems.size();
}
//----------------------------------------------------------------------------
JavaVirtualMachine::JavaVirtualMachine() {
}
JavaVirtualMachine::~JavaVirtualMachine(void) {
}
bool JavaVirtualMachine::StartJVM() {
Platform& platform = Platform::GetInstance();
Package& package = Package::GetInstance();
TString classpath = package.GetClassPath();
TString modulepath = package.GetModulePath();
JavaOptions options;
if (modulepath.empty() == false) {
options.AppendValue(_T("-Djava.module.path"), modulepath);
}
options.AppendValue(_T("-Djava.library.path"),
package.GetPackageAppDirectory() + FilePath::PathSeparator()
+ package.GetPackageLauncherDirectory());
options.AppendValue(
_T("-Djava.launcher.path"), package.GetPackageLauncherDirectory());
options.AppendValues(package.GetJavaOptions());
#ifdef DEBUG
if (package.Debugging() == dsJava) {
options.AppendValue(_T("-Xdebug"), _T(""));
options.AppendValue(
_T("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=localhost:5005"),
_T(""));
platform.ShowMessage(_T("localhost:5005"));
}
#endif // DEBUG
TString maxHeapSizeOption;
TString minHeapSizeOption;
if (package.GetMemoryState() == PackageBootFields::msAuto) {
TPlatformNumber memorySize = package.GetMemorySize();
TString memory =
PlatformString((size_t)memorySize).toString() + _T("m");
maxHeapSizeOption = TString(_T("-Xmx")) + memory;
options.AppendValue(maxHeapSizeOption, _T(""));
if (memorySize > 256)
minHeapSizeOption = _T("-Xms256m");
else
minHeapSizeOption = _T("-Xms") + memory;
options.AppendValue(minHeapSizeOption, _T(""));
}
TString mainClassName = package.GetMainClassName();
TString mainModule = package.GetMainModule();
if (mainClassName.empty() == true && mainModule.empty() == true) {
Messages& messages = Messages::GetInstance();
platform.ShowMessage(messages.GetMessage(NO_MAIN_CLASS_SPECIFIED));
return false;
}
configureLibrary();
// Initialize the arguments to JLI_Launch()
//
// On Mac OS X JLI_Launch spawns a new thread that actually starts the JVM.
// This new thread simply re-runs main(argc, argv). Therefore we do not
// want to add new args if we are still in the original main thread so we
// will treat them as command line args provided by the user ...
// Only propagate original set of args first time.
options.AppendValue(_T("-classpath"));
options.AppendValue(classpath);
std::list<TString> vmargs;
vmargs.push_back(package.GetCommandName());
if (package.HasSplashScreen() == true) {
options.AppendValue(TString(_T("-splash:"))
+ package.GetSplashScreenFileName(), _T(""));
}
if (mainModule.empty() == true) {
options.AppendValue(Helpers::ConvertJavaPathToId(mainClassName),
_T(""));
} else {
options.AppendValue(_T("-m"));
options.AppendValue(mainModule);
}
return launchVM(options, vmargs);
}
void JavaVirtualMachine::configureLibrary() {
Platform& platform = Platform::GetInstance();
Package& package = Package::GetInstance();
TString libName = package.GetJavaLibraryFileName();
platform.addPlatformDependencies(&javaLibrary);
javaLibrary.Load(libName);
}
bool JavaVirtualMachine::launchVM(JavaOptions& options,
std::list<TString>& vmargs) {
Platform& platform = Platform::GetInstance();
Package& package = Package::GetInstance();
#ifdef MAC
// Mac adds a ProcessSerialNumber to args when launched from .app
// filter out the psn since they it's not expected in the app
if (platform.IsMainThread() == false) {
std::list<TString> loptions = options.ToList();
vmargs.splice(vmargs.end(), loptions,
loptions.begin(), loptions.end());
}
#else
std::list<TString> loptions = options.ToList();
vmargs.splice(vmargs.end(), loptions, loptions.begin(), loptions.end());
#endif
std::list<TString> largs = package.GetArgs();
vmargs.splice(vmargs.end(), largs, largs.begin(), largs.end());
size_t argc = vmargs.size();
DynamicBuffer<char*> argv(argc + 1);
if (argv.GetData() == NULL) {
return false;
}
unsigned int index = 0;
for (std::list<TString>::const_iterator iterator = vmargs.begin();
iterator != vmargs.end(); iterator++) {
TString item = *iterator;
std::string arg = PlatformString(item).toStdString();
#ifdef DEBUG
printf("%i %s\n", index, arg.c_str());
#endif // DEBUG
argv[index] = PlatformString::duplicate(arg.c_str());
index++;
}
argv[argc] = NULL;
// On Mac we can only free the boot fields if the calling thread is
// not the main thread.
#ifdef MAC
if (platform.IsMainThread() == false) {
package.FreeBootFields();
}
#else
package.FreeBootFields();
#endif // MAC
if (javaLibrary.JavaVMCreate(argc, argv.GetData()) == true) {
return true;
}
for (index = 0; index < argc; index++) {
if (argv[index] != NULL) {
delete[] argv[index];
}
}
return false;
}

View File

@ -1,73 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef JAVAVIRTUALMACHINE_H
#define JAVAVIRTUALMACHINE_H
#include "jni.h"
#include "Platform.h"
#include "Library.h"
struct JavaOptionItem {
TString name;
TString value;
void* extraInfo;
};
class JavaOptions {
private:
std::list<JavaOptionItem> FItems;
JavaVMOption* FOptions;
public:
JavaOptions();
~JavaOptions();
void AppendValue(const TString Key, TString Value, void* Extra);
void AppendValue(const TString Key, TString Value);
void AppendValue(const TString Key);
void AppendValues(OrderedMap<TString, TString> Values);
void ReplaceValue(const TString Key, TString Value);
std::list<TString> ToList();
size_t GetCount();
};
class JavaVirtualMachine {
private:
JavaLibrary javaLibrary;
void configureLibrary();
bool launchVM(JavaOptions& options, std::list<TString>& vmargs);
public:
JavaVirtualMachine();
~JavaVirtualMachine(void);
bool StartJVM();
};
bool RunVM();
#endif // JAVAVIRTUALMACHINE_H

View File

@ -1,188 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "Library.h"
#include "Platform.h"
#include "Messages.h"
#include "PlatformString.h"
#include <fstream>
#include <locale>
Library::Library() {
Initialize();
}
Library::Library(const TString &FileName) {
Initialize();
Load(FileName);
}
Library::~Library() {
Unload();
}
void Library::Initialize() {
FModule = NULL;
FDependentLibraryNames = NULL;
FDependenciesLibraries = NULL;
}
void Library::InitializeDependencies() {
if (FDependentLibraryNames == NULL) {
FDependentLibraryNames = new std::vector<TString>();
}
if (FDependenciesLibraries == NULL) {
FDependenciesLibraries = new std::vector<Library*>();
}
}
void Library::LoadDependencies() {
if (FDependentLibraryNames != NULL && FDependenciesLibraries != NULL) {
for (std::vector<TString>::const_iterator iterator =
FDependentLibraryNames->begin();
iterator != FDependentLibraryNames->end(); iterator++) {
Library* library = new Library();
if (library->Load(*iterator) == true) {
FDependenciesLibraries->push_back(library);
}
}
delete FDependentLibraryNames;
FDependentLibraryNames = NULL;
}
}
void Library::UnloadDependencies() {
if (FDependenciesLibraries != NULL) {
for (std::vector<Library*>::const_iterator iterator =
FDependenciesLibraries->begin();
iterator != FDependenciesLibraries->end(); iterator++) {
Library* library = *iterator;
if (library != NULL) {
library->Unload();
delete library;
}
}
delete FDependenciesLibraries;
FDependenciesLibraries = NULL;
}
}
Procedure Library::GetProcAddress(const std::string& MethodName) const {
Platform& platform = Platform::GetInstance();
return platform.GetProcAddress(FModule, MethodName);
}
bool Library::Load(const TString &FileName) {
bool result = true;
if (FModule == NULL) {
LoadDependencies();
Platform& platform = Platform::GetInstance();
FModule = platform.LoadLibrary(FileName);
if (FModule == NULL) {
Messages& messages = Messages::GetInstance();
platform.ShowMessage(messages.GetMessage(LIBRARY_NOT_FOUND),
FileName);
result = false;
} else {
fname = PlatformString(FileName).toStdString();
}
}
return result;
}
bool Library::Unload() {
bool result = false;
if (FModule != NULL) {
Platform& platform = Platform::GetInstance();
platform.FreeLibrary(FModule);
FModule = NULL;
UnloadDependencies();
result = true;
}
return result;
}
void Library::AddDependency(const TString &FileName) {
InitializeDependencies();
if (FDependentLibraryNames != NULL) {
FDependentLibraryNames->push_back(FileName);
}
}
void Library::AddDependencies(const std::vector<TString> &Dependencies) {
if (Dependencies.size() > 0) {
InitializeDependencies();
if (FDependentLibraryNames != NULL) {
for (std::vector<TString>::const_iterator iterator =
FDependentLibraryNames->begin();
iterator != FDependentLibraryNames->end(); iterator++) {
TString fileName = *iterator;
AddDependency(fileName);
}
}
}
}
JavaLibrary::JavaLibrary() : Library(), FCreateProc(NULL) {
}
bool JavaLibrary::JavaVMCreate(size_t argc, char *argv[]) {
if (FCreateProc == NULL) {
FCreateProc = (JAVA_CREATE) GetProcAddress(LAUNCH_FUNC);
}
if (FCreateProc == NULL) {
Platform& platform = Platform::GetInstance();
Messages& messages = Messages::GetInstance();
platform.ShowMessage(
messages.GetMessage(FAILED_LOCATING_JVM_ENTRY_POINT));
return false;
}
return FCreateProc((int) argc, argv,
0, NULL,
0, NULL,
"",
"",
"java",
"java",
false,
false,
false,
0) == 0;
}

View File

@ -1,106 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef LIBRARY_H
#define LIBRARY_H
#include "PlatformDefs.h"
//#include "Platform.h"
#include "OrderedMap.h"
#include "jni.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string>
#include <map>
#include <list>
#include <vector>
#include <fstream>
using namespace std;
// Private typedef for function pointer casting
#if defined(_WIN32) && !defined(_WIN64)
#define LAUNCH_FUNC "_JLI_Launch@56"
#else
#define LAUNCH_FUNC "JLI_Launch"
#endif
typedef int (JNICALL *JAVA_CREATE)(int argc, char ** argv,
int jargc, const char** jargv,
int appclassc, const char** appclassv,
const char* fullversion,
const char* dotversion,
const char* pname,
const char* lname,
jboolean javaargs,
jboolean cpwildcard,
jboolean javaw,
jint ergo);
class Library {
private:
std::vector<TString> *FDependentLibraryNames;
std::vector<Library*> *FDependenciesLibraries;
Module FModule;
std::string fname;
void Initialize();
void InitializeDependencies();
void LoadDependencies();
void UnloadDependencies();
public:
void* GetProcAddress(const std::string& MethodName) const;
public:
Library();
Library(const TString &FileName);
~Library();
bool Load(const TString &FileName);
bool Unload();
const std::string& GetName() const {
return fname;
}
void AddDependency(const TString &FileName);
void AddDependencies(const std::vector<TString> &Dependencies);
};
class JavaLibrary : public Library {
JAVA_CREATE FCreateProc;
JavaLibrary(const TString &FileName);
public:
JavaLibrary();
bool JavaVMCreate(size_t argc, char *argv[]);
};
#endif // LIBRARY_H

View File

@ -1,74 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "Macros.h"
#include "Package.h"
#include "Helpers.h"
Macros::Macros(void) {
}
Macros::~Macros(void) {
}
void Macros::Initialize() {
Package& package = Package::GetInstance();
Macros& macros = Macros::GetInstance();
// Public macros.
macros.AddMacro(_T("$ROOTDIR"), package.GetPackageRootDirectory());
macros.AddMacro(_T("$APPDIR"), package.GetPackageAppDirectory());
macros.AddMacro(_T("$BINDIR"), package.GetPackageLauncherDirectory());
}
Macros& Macros::GetInstance() {
static Macros instance;
return instance;
}
TString Macros::ExpandMacros(TString Value) {
TString result = Value;
for (std::map<TString, TString>::iterator iterator = FData.begin();
iterator != FData.end();
iterator++) {
TString name = iterator->first;
if (Value.find(name) != TString::npos) {
TString lvalue = iterator->second;
result = Helpers::ReplaceString(Value, name, lvalue);
result = ExpandMacros(result);
break;
}
}
return result;
}
void Macros::AddMacro(TString Key, TString Value) {
FData.insert(std::map<TString, TString>::value_type(Key, Value));
}

View File

@ -1,62 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "Messages.h"
#include "Platform.h"
#include "FilePath.h"
#include "Helpers.h"
#include "Macros.h"
#include "JavaVirtualMachine.h"
Messages::Messages(void) {
FMessages.SetReadOnly(false);
FMessages.SetValue(LIBRARY_NOT_FOUND, _T("Failed to find library."));
FMessages.SetValue(FAILED_CREATING_JVM, _T("Failed to create JVM"));
FMessages.SetValue(FAILED_LOCATING_JVM_ENTRY_POINT,
_T("Failed to locate JLI_Launch"));
FMessages.SetValue(NO_MAIN_CLASS_SPECIFIED, _T("No main class specified"));
FMessages.SetValue(METHOD_NOT_FOUND, _T("No method %s in class %s."));
FMessages.SetValue(CLASS_NOT_FOUND, _T("Class %s not found."));
FMessages.SetValue(ERROR_INVOKING_METHOD, _T("Error invoking method."));
FMessages.SetValue(APPCDS_CACHE_FILE_NOT_FOUND,
_T("Error: AppCDS cache does not exists:\n%s\n"));
}
Messages& Messages::GetInstance() {
static Messages instance;
// Guaranteed to be destroyed. Instantiated on first use.
return instance;
}
Messages::~Messages(void) {
}
TString Messages::GetMessage(const TString Key) {
TString result;
FMessages.GetValue(Key, result);
Macros& macros = Macros::GetInstance();
result = macros.ExpandMacros(result);
return result;
}

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef MESSAGES_H
#define MESSAGES_H
#include "PropertyFile.h"
#define LIBRARY_NOT_FOUND _T("library.not.found")
#define FAILED_CREATING_JVM _T("failed.creating.jvm")
#define FAILED_LOCATING_JVM_ENTRY_POINT _T("failed.locating.jvm.entry.point")
#define NO_MAIN_CLASS_SPECIFIED _T("no.main.class.specified")
#define METHOD_NOT_FOUND _T("method.not.found")
#define CLASS_NOT_FOUND _T("class.not.found")
#define ERROR_INVOKING_METHOD _T("error.invoking.method")
#define CONFIG_FILE_NOT_FOUND _T("config.file.not.found")
#define BUNDLED_JVM_NOT_FOUND _T("bundled.jvm.not.found")
#define APPCDS_CACHE_FILE_NOT_FOUND _T("appcds.cache.file.not.found")
class Messages {
private:
PropertyFile FMessages;
Messages(void);
public:
static Messages& GetInstance();
~Messages(void);
TString GetMessage(const TString Key);
};
#endif // MESSAGES_H

View File

@ -1,271 +0,0 @@
/*
* Copyright (c) 2015, 2019, 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.
*/
#ifndef ORDEREDMAP_H
#define ORDEREDMAP_H
#include <map>
#include <vector>
#include <assert.h>
#include <stdexcept>
#include <iostream>
template <typename _T1, typename _T2>
struct JPPair
{
typedef _T1 first_type;
typedef _T2 second_type;
first_type first;
second_type second;
JPPair(first_type Value1, second_type Value2) {
first = Value1;
second = Value2;
}
};
template <typename TKey, typename TValue>
class OrderedMap {
public:
typedef TKey key_type;
typedef TValue mapped_type;
typedef JPPair<key_type, mapped_type> container_type;
typedef typename std::vector<container_type*>::iterator iterator;
typedef typename std::vector<container_type*>::const_iterator const_iterator;
private:
typedef std::map<key_type, container_type*> map_type;
typedef std::vector<container_type*> list_type;
map_type FMap;
list_type FList;
bool FAllowDuplicates;
typename list_type::iterator FindListItem(const key_type Key) {
typename list_type::iterator result = FList.end();
for (typename list_type::iterator iterator =
FList.begin(); iterator != FList.end(); iterator++) {
container_type *item = *iterator;
if (item->first == Key) {
result = iterator;
break;
}
}
return result;
}
public:
OrderedMap() {
FAllowDuplicates = false;
}
OrderedMap(const OrderedMap<key_type, mapped_type> &Value) {
Append(Value);
FAllowDuplicates = Value.GetAllowDuplicates();
}
~OrderedMap() {
Clear();
}
void SetAllowDuplicates(bool Value) {
FAllowDuplicates = Value;
}
bool GetAllowDuplicates() const {
return FAllowDuplicates;
}
iterator begin() {
return FList.begin();
}
const_iterator begin() const {
return FList.begin();
}
iterator end() {
return FList.end();
}
const_iterator end() const {
return FList.end();
}
void Clear() {
for (typename list_type::iterator iterator =
FList.begin(); iterator != FList.end(); iterator++) {
container_type *item = *iterator;
if (item != NULL) {
delete item;
item = NULL;
}
}
FMap.clear();
FList.clear();
}
bool ContainsKey(key_type Key) {
bool result = false;
if (FMap.find(Key) != FMap.end()) {
result = true;
}
return result;
}
std::vector<key_type> GetKeys() {
std::vector<key_type> result;
for (typename list_type::const_iterator iterator = FList.begin();
iterator != FList.end(); iterator++) {
container_type *item = *iterator;
result.push_back(item->first);
}
return result;
}
void Assign(const OrderedMap<key_type, mapped_type> &Value) {
Clear();
Append(Value);
}
void Append(const OrderedMap<key_type, mapped_type> &Value) {
for (size_t index = 0; index < Value.FList.size(); index++) {
container_type *item = Value.FList[index];
Append(item->first, item->second);
}
}
void Append(key_type Key, mapped_type Value) {
container_type *item = new container_type(Key, Value);
FMap.insert(std::pair<key_type, container_type*>(Key, item));
FList.push_back(item);
}
bool RemoveByKey(key_type Key) {
bool result = false;
typename list_type::iterator iterator = FindListItem(Key);
if (iterator != FList.end()) {
FMap.erase(Key);
FList.erase(iterator);
result = true;
}
return result;
}
bool GetValue(key_type Key, mapped_type &Value) {
bool result = false;
container_type* item = FMap[Key];
if (item != NULL) {
Value = item->second;
result = true;
}
return result;
}
bool SetValue(key_type Key, mapped_type &Value) {
bool result = false;
if ((FAllowDuplicates == false) && (ContainsKey(Key) == true)) {
container_type *item = FMap[Key];
if (item != NULL) {
item->second = Value;
result = true;
}
}
else {
Append(Key, Value);
result = true;
}
return result;
}
bool GetKey(int index, key_type &Value) {
if (index < 0 || index >= (int)FList.size()) {
return false;
}
container_type *item = FList.at(index);
if (item != NULL) {
Value = item->first;
return true;
}
return false;
}
bool GetValue(int index, mapped_type &Value) {
if (index < 0 || index >= (int)FList.size()) {
return false;
}
container_type *item = FList.at(index);
if (item != NULL) {
Value = item->second;
return true;
}
return false;
}
mapped_type &operator[](key_type Key) {
container_type* item = FMap[Key];
assert(item != NULL);
if (item != NULL) {
return item->second;
}
throw std::invalid_argument("Key not found");
}
OrderedMap& operator= (OrderedMap &Value) {
Clear();
FAllowDuplicates = Value.GetAllowDuplicates();
Append(Value);
return *this;
}
size_t Count() {
return FList.size();
}
};
#endif // ORDEREDMAP_H

View File

@ -1,557 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "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;
}
void Package::Initialize() {
if (FInitialized == true) {
return;
}
Platform& platform = Platform::GetInstance();
FBootFields = new PackageBootFields();
FDebugging = dsNone;
// Allow duplicates for Java options, so we can have multiple --add-exports
// or similar args.
FBootFields->FJavaOptions.SetAllowDuplicates(true);
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[JPACKAGE_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::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[JAVA_RUNTIME_KEY], FBootFields->FJavaRuntimeDirectory);
// Read jvmargs.
PromoteAppCDSState(config);
ReadJavaOptions(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 "AppCDSJavaOptions" section is present
// -> cdsAuto If "AppCDSJavaOptions" 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_APPCDSJAVAOPTIONS]) == 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::ReadJavaOptions(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_JAVAOPTIONS],
FBootFields->FJavaOptions);
break;
}
case cdsGenCache: {
Config->GetSection(keys[
CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS],
FBootFields->FJavaOptions);
break;
}
case cdsAuto:
case cdsEnabled: {
if (Config->GetValue(keys[CONFIG_SECTION_APPCDSJAVAOPTIONS],
_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_APPCDSJAVAOPTIONS],
_T( "-XX:SharedArchiveFile"),
FBootFields->FAppCDSCacheFileName);
}
}
Config->GetSection(keys[CONFIG_SECTION_APPCDSJAVAOPTIONS],
FBootFields->FJavaOptions);
}
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::GetJavaOptions() {
return FBootFields->FJavaOptions;
}
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::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::GetJavaLibraryFileName() {
assert(FBootFields != NULL);
if (FBootFields->FJavaLibraryFileName.empty() == true) {
Platform& platform = Platform::GetInstance();
Macros& macros = Macros::GetInstance();
TString jvmRuntimePath = macros.ExpandMacros(GetJavaRuntimeDirectory());
FBootFields->FJavaLibraryFileName =
platform.GetBundledJavaLibraryFileName(jvmRuntimePath);
}
return FBootFields->FJavaLibraryFileName;
}
TString Package::GetJavaRuntimeDirectory() {
assert(FBootFields != NULL);
return FBootFields->FJavaRuntimeDirectory;
}
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;
}

View File

@ -1,126 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef PACKAGE_H
#define PACKAGE_H
#include "Platform.h"
#include "PlatformString.h"
#include "FilePath.h"
#include "PropertyFile.h"
#include <map>
#include <list>
class PackageBootFields {
public:
enum MemoryState {msManual, msAuto};
public:
OrderedMap<TString, TString> FJavaOptions;
std::list<TString> FArgs;
TString FPackageRootDirectory;
TString FPackageAppDirectory;
TString FPackageLauncherDirectory;
TString FAppDataDirectory;
TString FPackageAppDataDirectory;
TString FClassPath;
TString FModulePath;
TString FMainJar;
TString FMainModule;
TString FMainClassName;
TString FJavaRuntimeDirectory;
TString FJavaLibraryFileName;
TString FSplashScreenFileName;
bool FUseJavaPreferences;
TString FCommandName;
TString FAppCDSCacheFileName;
TPlatformNumber FMemorySize;
MemoryState FMemoryState;
};
class Package {
private:
Package(Package const&); // Don't Implement.
void operator=(Package const&); // Don't implement
private:
bool FInitialized;
PackageBootFields* FBootFields;
TString FAppCDSCacheDirectory;
DebugState FDebugging;
Package(void);
TString GetMainJar();
void ReadJavaOptions(ISectionalPropertyContainer* Config);
void PromoteAppCDSState(ISectionalPropertyContainer* Config);
public:
static Package& GetInstance();
~Package(void);
void Initialize();
void Clear();
void FreeBootFields();
void SetCommandLineArguments(int argc, TCHAR* argv[]);
OrderedMap<TString, TString> GetJavaOptions();
TString GetMainModule();
std::list<TString> GetArgs();
TString GetPackageRootDirectory();
TString GetPackageAppDirectory();
TString GetPackageLauncherDirectory();
TString GetAppDataDirectory();
TString GetAppCDSCacheDirectory();
TString GetAppCDSCacheFileName();
TString GetPackageAppDataDirectory();
TString GetClassPath();
TString GetModulePath();
TString GetMainClassName();
TString GetJavaLibraryFileName();
TString GetJavaRuntimeDirectory();
TString GetSplashScreenFileName();
bool HasSplashScreen();
TString GetCommandName();
TPlatformNumber GetMemorySize();
PackageBootFields::MemoryState GetMemoryState();
DebugState Debugging();
};
#endif // PACKAGE_H

View File

@ -1,173 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "Platform.h"
#include "Messages.h"
#include "PlatformString.h"
#include "FilePath.h"
#include <fstream>
#include <locale>
#ifdef WINDOWS
#include "WindowsPlatform.h"
#endif // WINDOWS
#ifdef LINUX
#include "LinuxPlatform.h"
#endif // LINUX
#ifdef MAC
#include "MacPlatform.h"
#endif // MAC
Platform& Platform::GetInstance() {
#ifdef WINDOWS
static WindowsPlatform instance;
#endif // WINDOWS
#ifdef LINUX
static LinuxPlatform instance;
#endif // LINUX
#ifdef MAC
static MacPlatform instance;
#endif // MAC
return instance;
}
TString Platform::GetConfigFileName() {
TString result;
TString basedir = GetPackageAppDirectory();
if (basedir.empty() == false) {
basedir = FilePath::IncludeTrailingSeparator(basedir);
TString appConfig = basedir + GetAppName() + _T(".cfg");
if (FilePath::FileExists(appConfig) == true) {
result = appConfig;
}
else {
result = basedir + _T("package.cfg");
if (FilePath::FileExists(result) == false) {
result = _T("");
}
}
}
return result;
}
std::list<TString> Platform::LoadFromFile(TString FileName) {
std::list<TString> result;
if (FilePath::FileExists(FileName) == true) {
std::wifstream stream(FileName.data());
InitStreamLocale(&stream);
if (stream.is_open() == true) {
while (stream.eof() == false) {
std::wstring line;
std::getline(stream, line);
// # at the first character will comment out the line.
if (line.empty() == false && line[0] != '#') {
result.push_back(PlatformString(line).toString());
}
}
}
}
return result;
}
void Platform::SaveToFile(TString FileName, std::list<TString> Contents, bool ownerOnly) {
TString path = FilePath::ExtractFilePath(FileName);
if (FilePath::DirectoryExists(path) == false) {
FilePath::CreateDirectory(path, ownerOnly);
}
std::wofstream stream(FileName.data());
InitStreamLocale(&stream);
FilePath::ChangePermissions(FileName.data(), ownerOnly);
if (stream.is_open() == true) {
for (std::list<TString>::const_iterator iterator =
Contents.begin(); iterator != Contents.end(); iterator++) {
TString line = *iterator;
stream << PlatformString(line).toUnicodeString() << std::endl;
}
}
}
std::map<TString, TString> Platform::GetKeys() {
std::map<TString, TString> keys;
keys.insert(std::map<TString, TString>::value_type(CONFIG_VERSION,
_T("app.version")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINJAR_KEY,
_T("app.mainjar")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINMODULE_KEY,
_T("app.mainmodule")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_MAINCLASSNAME_KEY,
_T("app.mainclass")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_CLASSPATH_KEY,
_T("app.classpath")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_MODULEPATH_KEY,
_T("app.modulepath")));
keys.insert(std::map<TString, TString>::value_type(APP_NAME_KEY,
_T("app.name")));
keys.insert(std::map<TString, TString>::value_type(JAVA_RUNTIME_KEY,
_T("app.runtime")));
keys.insert(std::map<TString, TString>::value_type(JPACKAGE_APP_DATA_DIR,
_T("app.identifier")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_SPLASH_KEY,
_T("app.splash")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_MEMORY,
_T("app.memory")));
keys.insert(std::map<TString, TString>::value_type(CONFIG_APP_DEBUG,
_T("app.debug")));
keys.insert(std::map<TString,
TString>::value_type(CONFIG_APPLICATION_INSTANCE,
_T("app.application.instance")));
keys.insert(std::map<TString,
TString>::value_type(CONFIG_SECTION_APPLICATION,
_T("Application")));
keys.insert(std::map<TString,
TString>::value_type(CONFIG_SECTION_JAVAOPTIONS,
_T("JavaOptions")));
keys.insert(std::map<TString,
TString>::value_type(CONFIG_SECTION_APPCDSJAVAOPTIONS,
_T("AppCDSJavaOptions")));
keys.insert(std::map<TString,
TString>::value_type(CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS,
_T("AppCDSGenerateCacheJavaOptions")));
keys.insert(std::map<TString,
TString>::value_type(CONFIG_SECTION_ARGOPTIONS,
_T("ArgOptions")));
return keys;
}

View File

@ -1,264 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef PLATFORM_H
#define PLATFORM_H
#include "PlatformDefs.h"
#include "Properties.h"
#include "OrderedMap.h"
#include "Library.h"
#include <stdio.h>
#include <stdlib.h>
#include <memory.h>
#include <string>
#include <map>
#include <list>
#include <vector>
#include <fstream>
using namespace std;
// Config file sections
#define CONFIG_SECTION_APPLICATION _T("CONFIG_SECTION_APPLICATION")
#define CONFIG_SECTION_JAVAOPTIONS _T("CONFIG_SECTION_JAVAOPTIONS")
#define CONFIG_SECTION_APPCDSJAVAOPTIONS _T("CONFIG_SECTION_APPCDSJAVAOPTIONS")
#define CONFIG_SECTION_ARGOPTIONS _T("CONFIG_SECTION_ARGOPTIONS")
#define CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS \
_T("CONFIG_SECTION_APPCDSGENERATECACHEJAVAOPTIONS")
// Config file keys.
#define CONFIG_VERSION _T("CONFIG_VERSION")
#define CONFIG_MAINJAR_KEY _T("CONFIG_MAINJAR_KEY")
#define CONFIG_MAINMODULE_KEY _T("CONFIG_MAINMODULE_KEY")
#define CONFIG_MAINCLASSNAME_KEY _T("CONFIG_MAINCLASSNAME_KEY")
#define CONFIG_CLASSPATH_KEY _T("CONFIG_CLASSPATH_KEY")
#define CONFIG_MODULEPATH_KEY _T("CONFIG_MODULEPATH_KEY")
#define APP_NAME_KEY _T("APP_NAME_KEY")
#define CONFIG_SPLASH_KEY _T("CONFIG_SPLASH_KEY")
#define CONFIG_APP_MEMORY _T("CONFIG_APP_MEMORY")
#define CONFIG_APP_DEBUG _T("CONFIG_APP_DEBUG")
#define CONFIG_APPLICATION_INSTANCE _T("CONFIG_APPLICATION_INSTANCE")
#define JAVA_RUNTIME_KEY _T("JAVA_RUNTIME_KEY")
#define JPACKAGE_APP_DATA_DIR _T("CONFIG_APP_IDENTIFIER")
struct WideString {
size_t length;
wchar_t* data;
WideString() { length = 0; data = NULL; }
};
struct MultibyteString {
size_t length;
char* data;
MultibyteString() { length = 0; data = NULL; }
};
class Process {
protected:
std::list<TString> FOutput;
public:
Process() {
Output.SetInstance(this);
Input.SetInstance(this);
}
virtual ~Process() {}
virtual bool IsRunning() = 0;
virtual bool Terminate() = 0;
virtual bool Execute(const TString Application,
const std::vector<TString> Arguments, bool AWait = false) = 0;
virtual bool Wait() = 0;
virtual TProcessID GetProcessID() = 0;
virtual std::list<TString> GetOutput() { return FOutput; }
virtual void SetInput(TString Value) = 0;
ReadProperty<Process, std::list<TString>, &Process::GetOutput> Output;
WriteProperty<Process, TString, &Process::SetInput> Input;
};
template <typename T>
class AutoFreePtr {
private:
T* FObject;
public:
AutoFreePtr() {
FObject = NULL;
}
AutoFreePtr(T* Value) {
FObject = Value;
}
~AutoFreePtr() {
if (FObject != NULL) {
delete FObject;
}
}
operator T* () const {
return FObject;
}
T& operator* () const {
return *FObject;
}
T* operator->() const {
return FObject;
}
T** operator&() {
return &FObject;
}
T* operator=(const T * rhs) {
FObject = rhs;
return FObject;
}
};
enum DebugState {dsNone, dsNative, dsJava};
enum MessageResponse {mrOK, mrCancel};
enum AppCDSState {cdsUninitialized, cdsDisabled,
cdsEnabled, cdsAuto, cdsGenCache};
class Platform {
private:
AppCDSState FAppCDSState;
protected:
Platform(void): FAppCDSState(cdsUninitialized) {
}
public:
AppCDSState GetAppCDSState() { return FAppCDSState; }
void SetAppCDSState(AppCDSState Value) { FAppCDSState = Value; }
static Platform& GetInstance();
virtual ~Platform(void) {}
public:
virtual void ShowMessage(TString title, TString description) = 0;
virtual void ShowMessage(TString description) = 0;
virtual MessageResponse ShowResponseMessage(TString title,
TString description) = 0;
// Caller must free result using delete[].
virtual TCHAR* ConvertStringToFileSystemString(TCHAR* Source,
bool &release) = 0;
// Caller must free result using delete[].
virtual TCHAR* ConvertFileSystemStringToString(TCHAR* Source,
bool &release) = 0;
// Returns:
// Windows=C:\Users\<username>\AppData\Local
// Linux=~/.local
// Mac=~/Library/Application Support
virtual TString GetAppDataDirectory() = 0;
virtual TString GetPackageAppDirectory() = 0;
virtual TString GetPackageLauncherDirectory() = 0;
virtual TString GetPackageRuntimeBinDirectory() = 0;
virtual TString GetAppName() = 0;
virtual TString GetConfigFileName();
virtual TString GetBundledJavaLibraryFileName(TString RuntimePath) = 0;
// Caller must free result.
virtual ISectionalPropertyContainer* GetConfigFile(TString FileName) = 0;
virtual TString GetModuleFileName() = 0;
virtual TString GetPackageRootDirectory() = 0;
virtual Module LoadLibrary(TString FileName) = 0;
virtual void FreeLibrary(Module Module) = 0;
virtual Procedure GetProcAddress(Module Module, std::string MethodName) = 0;
// Caller must free result.
virtual Process* CreateProcess() = 0;
virtual bool IsMainThread() = 0;
// Returns megabytes.
virtual TPlatformNumber GetMemorySize() = 0;
virtual std::map<TString, TString> GetKeys();
virtual void InitStreamLocale(wios *stream) = 0;
virtual std::list<TString> LoadFromFile(TString FileName);
virtual void SaveToFile(TString FileName,
std::list<TString> Contents, bool ownerOnly);
virtual TString GetTempDirectory() = 0;
virtual void addPlatformDependencies(JavaLibrary *pJavaLibrary) = 0;
public:
// String helpers
// Caller must free result using delete[].
static void CopyString(char *Destination,
size_t NumberOfElements, const char *Source);
// Caller must free result using delete[].
static void CopyString(wchar_t *Destination,
size_t NumberOfElements, const wchar_t *Source);
static WideString MultibyteStringToWideString(const char* value);
static MultibyteString WideStringToMultibyteString(const wchar_t* value);
};
class Exception: public std::exception {
private:
TString FMessage;
protected:
void SetMessage(const TString Message) {
FMessage = Message;
}
public:
explicit Exception() : exception() {}
explicit Exception(const TString Message) : exception() {
SetMessage(Message);
}
virtual ~Exception() throw() {}
TString GetMessage() { return FMessage; }
};
#endif // PLATFORM_H

View File

@ -1,227 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "PlatformString.h"
#include "Helpers.h"
#include <stdio.h>
#include <stdlib.h>
#include <stdlib.h>
#include <memory.h>
#include <sstream>
#include <string.h>
#include "jni.h"
void PlatformString::initialize() {
FWideTStringToFree = NULL;
FLength = 0;
FData = NULL;
}
PlatformString::PlatformString(void) {
initialize();
}
PlatformString::~PlatformString(void) {
if (FData != NULL) {
delete[] FData;
}
if (FWideTStringToFree != NULL) {
delete[] FWideTStringToFree;
}
}
PlatformString::PlatformString(const PlatformString &value) {
initialize();
FLength = value.FLength;
FData = new char[FLength + 1];
Platform::CopyString(FData, FLength + 1, value.FData);
}
PlatformString::PlatformString(const char* value) {
initialize();
FLength = strlen(value);
FData = new char[FLength + 1];
Platform::CopyString(FData, FLength + 1, value);
}
PlatformString::PlatformString(size_t Value) {
initialize();
std::stringstream ss;
std::string s;
ss << Value;
s = ss.str();
FLength = strlen(s.c_str());
FData = new char[FLength + 1];
Platform::CopyString(FData, FLength + 1, s.c_str());
}
PlatformString::PlatformString(const wchar_t* value) {
initialize();
MultibyteString temp = Platform::WideStringToMultibyteString(value);
FLength = temp.length;
FData = temp.data;
}
PlatformString::PlatformString(const std::string &value) {
initialize();
const char* lvalue = value.data();
FLength = value.size();
FData = new char[FLength + 1];
Platform::CopyString(FData, FLength + 1, lvalue);
}
PlatformString::PlatformString(const std::wstring &value) {
initialize();
const wchar_t* lvalue = value.data();
MultibyteString temp = Platform::WideStringToMultibyteString(lvalue);
FLength = temp.length;
FData = temp.data;
}
TString PlatformString::Format(const TString value, ...) {
TString result = value;
va_list arglist;
va_start(arglist, value);
while (1) {
size_t pos = result.find(_T("%s"), 0);
if (pos == TString::npos) {
break;
}
else {
TCHAR* arg = va_arg(arglist, TCHAR*);
if (arg == NULL) {
break;
}
else {
result.replace(pos, StringLength(_T("%s")), arg);
}
}
}
va_end(arglist);
return result;
}
size_t PlatformString::length() {
return FLength;
}
char* PlatformString::c_str() {
return FData;
}
char* PlatformString::toMultibyte() {
return FData;
}
wchar_t* PlatformString::toWideString() {
WideString result = Platform::MultibyteStringToWideString(FData);
if (result.data != NULL) {
if (FWideTStringToFree != NULL) {
delete [] FWideTStringToFree;
}
FWideTStringToFree = result.data;
}
return result.data;
}
std::wstring PlatformString::toUnicodeString() {
std::wstring result;
wchar_t* data = toWideString();
if (FLength != 0 && data != NULL) {
// NOTE: Cleanup of result is handled by PlatformString destructor.
result = data;
}
return result;
}
std::string PlatformString::toStdString() {
std::string result;
char* data = toMultibyte();
if (FLength > 0 && data != NULL) {
result = data;
}
return result;
}
TCHAR* PlatformString::toPlatformString() {
#ifdef _UNICODE
return toWideString();
#else
return c_str();
#endif //_UNICODE
}
TString PlatformString::toString() {
#ifdef _UNICODE
return toUnicodeString();
#else
return toStdString();
#endif //_UNICODE
}
PlatformString::operator char* () {
return c_str();
}
PlatformString::operator wchar_t* () {
return toWideString();
}
PlatformString::operator std::wstring () {
return toUnicodeString();
}
char* PlatformString::duplicate(const char* Value) {
size_t length = strlen(Value);
char* result = new char[length + 1];
Platform::CopyString(result, length + 1, Value);
return result;
}
wchar_t* PlatformString::duplicate(const wchar_t* Value) {
size_t length = wcslen(Value);
wchar_t* result = new wchar_t[length + 1];
Platform::CopyString(result, length + 1, Value);
return result;
}

View File

@ -1,136 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef PLATFORMSTRING_H
#define PLATFORMSTRING_H
#include <string>
#include <list>
#include <stdio.h>
#include <stdlib.h>
#include "jni.h"
#include "Platform.h"
template <typename T>
class DynamicBuffer {
private:
T* FData;
size_t FSize;
public:
DynamicBuffer(size_t Size) {
FSize = 0;
FData = NULL;
Resize(Size);
}
~DynamicBuffer() {
delete[] FData;
}
T* GetData() { return FData; }
size_t GetSize() { return FSize; }
bool Resize(size_t Size) {
FSize = Size;
if (FData != NULL) {
delete[] FData;
FData = NULL;
}
if (FSize != 0) {
FData = new T[FSize];
if (FData != NULL) {
Zero();
} else {
return false;
}
}
return true;
}
void Zero() {
memset(FData, 0, FSize * sizeof(T));
}
T& operator[](size_t index) {
return FData[index];
}
};
class PlatformString {
private:
char* FData; // Stored as UTF-8
size_t FLength;
wchar_t* FWideTStringToFree;
void initialize();
// Prohibit Heap-Based PlatformStrings
private:
static void *operator new(size_t size);
static void operator delete(void *ptr);
public:
PlatformString(void);
PlatformString(const PlatformString &value);
PlatformString(const char* value);
PlatformString(const wchar_t* value);
PlatformString(const std::string &value);
PlatformString(const std::wstring &value);
PlatformString(size_t Value);
static TString Format(const TString value, ...);
~PlatformString(void);
size_t length();
char* c_str();
char* toMultibyte();
wchar_t* toWideString();
std::wstring toUnicodeString();
std::string toStdString();
TCHAR* toPlatformString();
TString toString();
operator char* ();
operator wchar_t* ();
operator std::wstring ();
// Caller must free result using delete[].
static char* duplicate(const char* Value);
// Caller must free result using delete[].
static wchar_t* duplicate(const wchar_t* Value);
};
#endif // PLATFORMSTRING_H

View File

@ -1,184 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef PROPERTIES_H
#define PROPERTIES_H
#include "PlatformDefs.h"
#include "OrderedMap.h"
//#include <stdio.h>
//#include <stdlib.h>
//#include <memory.h>
//#include <string>
//#include <map>
//#include <list>
//#include <vector>
//#include <fstream>
//using namespace std;
template <typename ObjectType, typename ValueType,
ValueType (ObjectType::*getter)(void),
void (ObjectType::*setter)(ValueType)>
class Property {
private:
ObjectType* FObject;
public:
Property() {
FObject = NULL;
}
void SetInstance(ObjectType* Value) {
FObject = Value;
}
// To set the value using the set method.
ValueType operator =(const ValueType& Value) {
assert(FObject != NULL);
(FObject->*setter)(Value);
return Value;
}
// The Property class is treated as the internal type.
operator ValueType() {
assert(FObject != NULL);
return (FObject->*getter)();
}
};
template <typename ObjectType, typename ValueType,
ValueType (ObjectType::*getter)(void)>
class ReadProperty {
private:
ObjectType* FObject;
public:
ReadProperty() {
FObject = NULL;
}
void SetInstance(ObjectType* Value) {
FObject = Value;
}
// The Property class is treated as the internal type.
operator ValueType() {
assert(FObject != NULL);
return (FObject->*getter)();
}
};
template <typename ObjectType, typename ValueType,
void (ObjectType::*setter)(ValueType)>
class WriteProperty {
private:
ObjectType* FObject;
public:
WriteProperty() {
FObject = NULL;
}
void SetInstance(ObjectType* Value) {
FObject = Value;
}
// To set the value using the set method.
ValueType operator =(const ValueType& Value) {
assert(FObject != NULL);
(FObject->*setter)(Value);
return Value;
}
};
template <typename ValueType,
ValueType (*getter)(void), void (*setter)(ValueType)>
class StaticProperty {
public:
StaticProperty() {
}
// To set the value using the set method.
ValueType operator =(const ValueType& Value) {
(*getter)(Value);
return Value;
}
// The Property class is treated as the internal type which is the getter.
operator ValueType() {
return (*setter)();
}
};
template <typename ValueType, ValueType (*getter)(void)>
class StaticReadProperty {
public:
StaticReadProperty() {
}
// The Property class is treated as the internal type which is the getter.
operator ValueType() {
return (*getter)();
}
};
template <typename ValueType, void (*setter)(ValueType)>
class StaticWriteProperty {
public:
StaticWriteProperty() {
}
// To set the value using the set method.
ValueType operator =(const ValueType& Value) {
(*setter)(Value);
return Value;
}
};
class IPropertyContainer {
public:
IPropertyContainer(void) {}
virtual ~IPropertyContainer(void) {}
virtual bool GetValue(const TString Key, TString& Value) = 0;
virtual size_t GetCount() = 0;
};
class ISectionalPropertyContainer {
public:
ISectionalPropertyContainer(void) {}
virtual ~ISectionalPropertyContainer(void) {}
virtual bool GetValue(const TString SectionName,
const TString Key, TString& Value) = 0;
virtual bool ContainsSection(const TString SectionName) = 0;
virtual bool GetSection(const TString SectionName,
OrderedMap<TString, TString> &Data) = 0;
};
#endif // PROPERTIES_H

View File

@ -1,168 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "PropertyFile.h"
#include "Helpers.h"
#include "FilePath.h"
#include <string>
PropertyFile::PropertyFile(void) : IPropertyContainer() {
FReadOnly = false;
FModified = false;
}
PropertyFile::PropertyFile(const TString FileName) : IPropertyContainer() {
FReadOnly = true;
FModified = false;
LoadFromFile(FileName);
}
PropertyFile::PropertyFile(OrderedMap<TString, TString> Value) {
FData.Append(Value);
}
PropertyFile::PropertyFile(PropertyFile &Value) {
FData = Value.FData;
FReadOnly = Value.FReadOnly;
FModified = Value.FModified;
}
PropertyFile::~PropertyFile(void) {
FData.Clear();
}
void PropertyFile::SetModified(bool Value) {
FModified = Value;
}
bool PropertyFile::IsModified() {
return FModified;
}
bool PropertyFile::GetReadOnly() {
return FReadOnly;
}
void PropertyFile::SetReadOnly(bool Value) {
FReadOnly = Value;
}
bool PropertyFile::LoadFromFile(const TString FileName) {
bool result = false;
Platform& platform = Platform::GetInstance();
std::list<TString> contents = platform.LoadFromFile(FileName);
if (contents.empty() == false) {
for (std::list<TString>::const_iterator iterator = contents.begin();
iterator != contents.end(); iterator++) {
TString line = *iterator;
TString name;
TString value;
if (Helpers::SplitOptionIntoNameValue(line, name, value) == true) {
FData.Append(name, value);
}
}
SetModified(false);
result = true;
}
return result;
}
bool PropertyFile::SaveToFile(const TString FileName, bool ownerOnly) {
bool result = false;
if (GetReadOnly() == false && IsModified()) {
std::list<TString> contents;
std::vector<TString> keys = FData.GetKeys();
for (size_t index = 0; index < keys.size(); index++) {
TString name = keys[index];
try {
TString value;// = FData[index];
if (FData.GetValue(name, value) == true) {
TString line = name + _T('=') + value;
contents.push_back(line);
}
}
catch (std::out_of_range &) {
}
}
Platform& platform = Platform::GetInstance();
platform.SaveToFile(FileName, contents, ownerOnly);
SetModified(false);
result = true;
}
return result;
}
bool PropertyFile::GetValue(const TString Key, TString& Value) {
return FData.GetValue(Key, Value);
}
bool PropertyFile::SetValue(const TString Key, TString Value) {
bool result = false;
if (GetReadOnly() == false) {
FData.SetValue(Key, Value);
SetModified(true);
result = true;
}
return result;
}
bool PropertyFile::RemoveKey(const TString Key) {
bool result = false;
if (GetReadOnly() == false) {
result = FData.RemoveByKey(Key);
if (result == true) {
SetModified(true);
}
}
return result;
}
size_t PropertyFile::GetCount() {
return FData.Count();
}
OrderedMap<TString, TString> PropertyFile::GetData() {
return FData;
}

View File

@ -1,65 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef PROPERTYFILE_H
#define PROPERTYFILE_H
#include "Platform.h"
#include "Helpers.h"
class PropertyFile : public IPropertyContainer {
private:
bool FReadOnly;
bool FModified;
OrderedMap<TString, TString> FData;
void SetModified(bool Value);
public:
PropertyFile(void);
PropertyFile(const TString FileName);
PropertyFile(OrderedMap<TString, TString> Value);
PropertyFile(PropertyFile &Value);
virtual ~PropertyFile(void);
bool IsModified();
bool GetReadOnly();
void SetReadOnly(bool Value);
bool LoadFromFile(const TString FileName);
bool SaveToFile(const TString FileName, bool ownerOnly = true);
bool SetValue(const TString Key, TString Value);
bool RemoveKey(const TString Key);
OrderedMap<TString, TString> GetData();
// IPropertyContainer
virtual bool GetValue(const TString Key, TString& Value);
virtual size_t GetCount();
};
#endif // PROPERTYFILE_H

View File

@ -1,180 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "Platform.h"
#include "PlatformString.h"
#include "FilePath.h"
#include "PropertyFile.h"
#include "JavaVirtualMachine.h"
#include "Package.h"
#include "Macros.h"
#include "Messages.h"
#include <stdio.h>
#include <signal.h>
#include <stdlib.h>
/*
This is the app launcher program for application packaging on Windows, Mac,
and Linux.
Basic approach:
- Launcher (jpackageapplauncher) is executable that loads
applauncher.dll/libapplauncher.dylib/libapplauncher.so
and calls start_launcher below.
- Reads app/package.cfg or Info.plist or app/<appname>.cfg for application
launch configuration (package.cfg is property file).
- Load Java with requested Java settings (bundled client Java if availble,
server or installed Java otherwise).
- Wait for Java to exit and then exit from Main
- To debug application by passing command line argument.
- Application folder is added to the library path (so LoadLibrary()) works.
Limitations and future work:
- Running Java code in primordial thread may cause problems
(example: can not use custom stack size).
Solution used by java launcher is to create a new thread to invoke Java.
See CR 6316197 for more information.
*/
extern "C" {
JNIEXPORT bool start_launcher(int argc, TCHAR* argv[]) {
bool result = false;
bool parentProcess = true;
// Platform must be initialize first.
Platform& platform = Platform::GetInstance();
try {
for (int index = 0; index < argc; index++) {
TString argument = argv[index];
if (argument == _T("-Xappcds:generatecache")) {
platform.SetAppCDSState(cdsGenCache);
}
else if (argument == _T("-Xappcds:off")) {
platform.SetAppCDSState(cdsDisabled);
}
else if (argument == _T("-Xapp:child")) {
parentProcess = false;
}
}
// Package must be initialized after Platform is fully initialized.
Package& package = Package::GetInstance();
Macros::Initialize();
package.SetCommandLineArguments(argc, argv);
switch (platform.GetAppCDSState()) {
case cdsDisabled:
case cdsUninitialized:
case cdsEnabled: {
break;
}
case cdsGenCache: {
TString cacheDirectory = package.GetAppCDSCacheDirectory();
if (FilePath::DirectoryExists(cacheDirectory) == false) {
FilePath::CreateDirectory(cacheDirectory, true);
} else {
TString cacheFileName =
package.GetAppCDSCacheFileName();
if (FilePath::FileExists(cacheFileName) == true) {
FilePath::DeleteFile(cacheFileName);
}
}
break;
}
case cdsAuto: {
TString cacheFileName = package.GetAppCDSCacheFileName();
if (parentProcess == true &&
FilePath::FileExists(cacheFileName) == false) {
AutoFreePtr<Process> process = platform.CreateProcess();
std::vector<TString> args;
args.push_back(_T("-Xappcds:generatecache"));
args.push_back(_T("-Xapp:child"));
process->Execute(
platform.GetModuleFileName(), args, true);
if (FilePath::FileExists(cacheFileName) == false) {
// Cache does not exist after trying to generate it,
// so run without cache.
platform.SetAppCDSState(cdsDisabled);
package.Clear();
package.Initialize();
}
}
break;
}
}
// Validation
switch (platform.GetAppCDSState()) {
case cdsDisabled:
case cdsGenCache: {
// Do nothing.
break;
}
case cdsEnabled:
case cdsAuto: {
TString cacheFileName =
package.GetAppCDSCacheFileName();
if (FilePath::FileExists(cacheFileName) == false) {
Messages& messages = Messages::GetInstance();
TString message = PlatformString::Format(
messages.GetMessage(
APPCDS_CACHE_FILE_NOT_FOUND),
cacheFileName.data());
throw Exception(message);
}
break;
}
case cdsUninitialized: {
platform.ShowMessage(_T("Internal Error"));
break;
}
}
// Run App
result = RunVM();
} catch (Exception &e) {
platform.ShowMessage(e.GetMessage());
}
return result;
}
JNIEXPORT void stop_launcher() {
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,27 +23,22 @@
* questions. * questions.
*/ */
#ifndef MACROS_H #include "PlatformLogEvent.h"
#define MACROS_H #include "Log.h"
#include "Platform.h"
#include <map>
class Macros { void LogEvent::init(PlatformLogEvent& logEvent) {
private: }
std::map<TString, TString> FData;
Macros(void);
public: void LogEvent::appendFormatted(const PlatformLogEvent& logEvent,
static Macros& GetInstance(); tstring& buffer) {
static void Initialize(); }
~Macros(void);
TString ExpandMacros(TString Value);
void AddMacro(TString Key, TString Value);
};
#endif // MACROS_H void Logger::initializingLogging() {
}
void Logger::initializeLogging() {
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,13 +23,11 @@
* questions. * questions.
*/ */
#include <windows.h> #ifndef PlatformLogEvent_h
#define PlatformLogEvent_h
extern "C" {
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, struct PlatformLogEvent {
LPVOID lpvReserved) { };
return true;
}
}
#endif // PlatformLogEvent_h

View File

@ -0,0 +1,68 @@
/*
* Copyright (c) 2020, 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 <dlfcn.h>
#include "Dll.h"
#include "FileUtils.h"
#include "ErrorHandling.h"
namespace {
HMODULE loadLibrary(const tstring& path) {
HMODULE h = dlopen(path.c_str(), RTLD_LAZY);
if (!h) {
JP_THROW(tstrings::any() << "dlopen(" << path
<< ") failed. Error: " << dlerror());
}
return h;
}
} // namesace
Dll::Dll(const tstrings::any &libPath): thePath(libPath.tstr()),
handle(loadLibrary(thePath)) {
}
Dll::Dll(const Dll& other): thePath(other.thePath),
handle(loadLibrary(thePath)) {
}
void* Dll::getFunction(const std::string &name, bool throwIfNotFound) const {
void *ptr = dlsym(handle.get(), name.c_str());
if (throwIfNotFound && !ptr) {
JP_THROW(tstrings::any() << "dlsym(" << thePath
<< ", " << name << ") failed. Error: " << dlerror());
}
return ptr;
}
/*static*/
void Dll::freeLibrary(HMODULE h) {
if (h) {
dlclose(h);
}
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,45 +23,43 @@
* questions. * questions.
*/ */
#ifndef PLATFORM_DEFS_H
#define PLATFORM_DEFS_H
#include <errno.h> #include <limits.h>
#include <unistd.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <dlfcn.h> #include <unistd.h>
#include <libgen.h> #include "FileUtils.h"
#include <string> #include "ErrorHandling.h"
using namespace std;
#ifndef LINUX namespace FileUtils {
#define LINUX
#endif
#define _T(x) x bool isFileExists(const tstring &filePath) {
struct stat statBuffer;
return (stat(filePath.c_str(), &statBuffer) != -1);
}
typedef char TCHAR;
typedef std::string TString;
#define StringLength strlen
typedef unsigned long DWORD; tstring toAbsolutePath(const tstring& path) {
if (path.empty()) {
char buffer[PATH_MAX] = { 0 };
char* buf = getcwd(buffer, sizeof(buffer));
if (buf) {
tstring result(buf);
if (result.empty()) {
JP_THROW(tstrings::any() << "getcwd() returned empty string");
}
return result;
}
#define TRAILING_PATHSEPARATOR '/' JP_THROW(tstrings::any() << "getcwd() failed. Error: "
#define BAD_TRAILING_PATHSEPARATOR '\\' << lastCRTError());
#define PATH_SEPARATOR ':' }
#define BAD_PATH_SEPARATOR ';'
#define MAX_PATH 1000
typedef long TPlatformNumber; if (isDirSeparator(path[0])) {
typedef pid_t TProcessID; return path;
}
#define HMODULE void* return mkpath() << toAbsolutePath("") << path;
}
typedef void* Module; } // namespace FileUtils
typedef void* Procedure;
#define StringToFileSystemString PlatformString
#define FileSystemStringToString PlatformString
#endif // PLATFORM_DEFS_H

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2020, 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 <stdlib.h>
#include "SysInfo.h"
#include "UnixSysInfo.h"
#include "ErrorHandling.h"
namespace SysInfo {
tstring getEnvVariable(const tstring& name) {
char *value = ::getenv(name.c_str());
if (!value) {
JP_THROW(tstrings::any() << "getenv("
<< name
<< ") failed. Variable not set");
}
return tstring(value);
}
tstring getEnvVariable(const std::nothrow_t&, const tstring& name,
const tstring& defValue) {
char *value = ::getenv(name.c_str());
if (value) {
return tstring(value);
}
return defValue;
}
bool isEnvVariableSet(const tstring& name) {
return ::getenv(name.c_str()) != 0;
}
tstring_array getCommandArgs(CommandArgProgramNameMode progNameMode) {
tstring_array result;
for (int i = progNameMode == ExcludeProgramName ? 1 : 0; i < argc; i++) {
result.push_back(argv[i]);
}
return result;
}
int argc = 0;
char** argv = 0;
} // end of namespace SysInfo

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2020, 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.
*/
#ifndef UnixSysInfo_h
#define UnixSysInfo_h
namespace SysInfo {
extern int argc;
extern char** argv;
} // UnixSysInfo
#endif // UnixSysInfo_h

View File

@ -1,331 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "FileAttributes.h"
#include <algorithm>
#include <list>
#include <sys/stat.h>
FileAttributes::FileAttributes(const TString FileName, bool FollowLink) {
FFileName = FileName;
FFollowLink = FollowLink;
ReadAttributes();
}
bool FileAttributes::WriteAttributes() {
bool result = false;
mode_t attributes = 0;
for (std::vector<FileAttribute>::const_iterator iterator =
FAttributes.begin();
iterator != FAttributes.end(); iterator++) {
switch (*iterator) {
case faBlockSpecial:
{
attributes |= S_IFBLK;
break;
}
case faCharacterSpecial:
{
attributes |= S_IFCHR;
break;
}
case faFIFOSpecial:
{
attributes |= S_IFIFO;
break;
}
case faNormal:
{
attributes |= S_IFREG;
break;
}
case faDirectory:
{
attributes |= S_IFDIR;
break;
}
case faSymbolicLink:
{
attributes |= S_IFLNK;
break;
}
case faSocket:
{
attributes |= S_IFSOCK;
break;
}
// Owner
case faReadOnly:
{
attributes |= S_IRUSR;
break;
}
case faWriteOnly:
{
attributes |= S_IWUSR;
break;
}
case faReadWrite:
{
attributes |= S_IRUSR;
attributes |= S_IWUSR;
break;
}
case faExecute:
{
attributes |= S_IXUSR;
break;
}
// Group
case faGroupReadOnly:
{
attributes |= S_IRGRP;
break;
}
case faGroupWriteOnly:
{
attributes |= S_IWGRP;
break;
}
case faGroupReadWrite:
{
attributes |= S_IRGRP;
attributes |= S_IWGRP;
break;
}
case faGroupExecute:
{
attributes |= S_IXGRP;
break;
}
// Others
case faOthersReadOnly:
{
attributes |= S_IROTH;
break;
}
case faOthersWriteOnly:
{
attributes |= S_IWOTH;
break;
}
case faOthersReadWrite:
{
attributes |= S_IROTH;
attributes |= S_IWOTH;
break;
}
case faOthersExecute:
{
attributes |= S_IXOTH;
break;
}
default:
break;
}
}
if (chmod(FFileName.data(), attributes) == 0) {
result = true;
}
return result;
}
#define S_ISRUSR(m) (((m) & S_IRWXU) == S_IRUSR)
#define S_ISWUSR(m) (((m) & S_IRWXU) == S_IWUSR)
#define S_ISXUSR(m) (((m) & S_IRWXU) == S_IXUSR)
#define S_ISRGRP(m) (((m) & S_IRWXG) == S_IRGRP)
#define S_ISWGRP(m) (((m) & S_IRWXG) == S_IWGRP)
#define S_ISXGRP(m) (((m) & S_IRWXG) == S_IXGRP)
#define S_ISROTH(m) (((m) & S_IRWXO) == S_IROTH)
#define S_ISWOTH(m) (((m) & S_IRWXO) == S_IWOTH)
#define S_ISXOTH(m) (((m) & S_IRWXO) == S_IXOTH)
bool FileAttributes::ReadAttributes() {
bool result = false;
struct stat status;
if (stat(StringToFileSystemString(FFileName), &status) == 0) {
result = true;
if (S_ISBLK(status.st_mode) != 0) {
FAttributes.push_back(faBlockSpecial);
}
if (S_ISCHR(status.st_mode) != 0) {
FAttributes.push_back(faCharacterSpecial);
}
if (S_ISFIFO(status.st_mode) != 0) {
FAttributes.push_back(faFIFOSpecial);
}
if (S_ISREG(status.st_mode) != 0) {
FAttributes.push_back(faNormal);
}
if (S_ISDIR(status.st_mode) != 0) {
FAttributes.push_back(faDirectory);
}
if (S_ISLNK(status.st_mode) != 0) {
FAttributes.push_back(faSymbolicLink);
}
if (S_ISSOCK(status.st_mode) != 0) {
FAttributes.push_back(faSocket);
}
// Owner
if (S_ISRUSR(status.st_mode) != 0) {
if (S_ISWUSR(status.st_mode) != 0) {
FAttributes.push_back(faReadWrite);
} else {
FAttributes.push_back(faReadOnly);
}
} else if (S_ISWUSR(status.st_mode) != 0) {
FAttributes.push_back(faWriteOnly);
}
if (S_ISXUSR(status.st_mode) != 0) {
FAttributes.push_back(faExecute);
}
// Group
if (S_ISRGRP(status.st_mode) != 0) {
if (S_ISWGRP(status.st_mode) != 0) {
FAttributes.push_back(faGroupReadWrite);
} else {
FAttributes.push_back(faGroupReadOnly);
}
} else if (S_ISWGRP(status.st_mode) != 0) {
FAttributes.push_back(faGroupWriteOnly);
}
if (S_ISXGRP(status.st_mode) != 0) {
FAttributes.push_back(faGroupExecute);
}
// Others
if (S_ISROTH(status.st_mode) != 0) {
if (S_ISWOTH(status.st_mode) != 0) {
FAttributes.push_back(faOthersReadWrite);
} else {
FAttributes.push_back(faOthersReadOnly);
}
} else if (S_ISWOTH(status.st_mode) != 0) {
FAttributes.push_back(faOthersWriteOnly);
}
if (S_ISXOTH(status.st_mode) != 0) {
FAttributes.push_back(faOthersExecute);
}
if (FFileName.size() > 0 && FFileName[0] == '.') {
FAttributes.push_back(faHidden);
}
}
return result;
}
bool FileAttributes::Valid(const FileAttribute Value) {
bool result = false;
switch (Value) {
case faReadWrite:
case faWriteOnly:
case faExecute:
case faGroupReadWrite:
case faGroupWriteOnly:
case faGroupReadOnly:
case faGroupExecute:
case faOthersReadWrite:
case faOthersWriteOnly:
case faOthersReadOnly:
case faOthersExecute:
case faReadOnly:
result = true;
break;
default:
break;
}
return result;
}
void FileAttributes::Append(FileAttribute Value) {
if (Valid(Value) == true) {
if ((Value == faReadOnly && Contains(faWriteOnly) == true) ||
(Value == faWriteOnly && Contains(faReadOnly) == true)) {
Value = faReadWrite;
}
FAttributes.push_back(Value);
WriteAttributes();
}
}
bool FileAttributes::Contains(FileAttribute Value) {
bool result = false;
std::vector<FileAttribute>::const_iterator iterator =
std::find(FAttributes.begin(), FAttributes.end(), Value);
if (iterator != FAttributes.end()) {
result = true;
}
return result;
}
void FileAttributes::Remove(FileAttribute Value) {
if (Valid(Value) == true) {
if (Value == faReadOnly && Contains(faReadWrite) == true) {
Append(faWriteOnly);
Remove(faReadWrite);
} else if (Value == faWriteOnly && Contains(faReadWrite) == true) {
Append(faReadOnly);
Remove(faReadWrite);
}
std::vector<FileAttribute>::iterator iterator =
std::find(FAttributes.begin(), FAttributes.end(), Value);
if (iterator != FAttributes.end()) {
FAttributes.erase(iterator);
WriteAttributes();
}
}
}

View File

@ -1,197 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "PlatformDefs.h"
#include "FilePath.h"
#include <algorithm>
#include <list>
#include <sys/stat.h>
bool FilePath::FileExists(const TString FileName) {
bool result = false;
struct stat buf;
if ((stat(StringToFileSystemString(FileName), &buf) == 0) &&
(S_ISREG(buf.st_mode) != 0)) {
result = true;
}
return result;
}
bool FilePath::DirectoryExists(const TString DirectoryName) {
bool result = false;
struct stat buf;
if ((stat(StringToFileSystemString(DirectoryName), &buf) == 0) &&
(S_ISDIR(buf.st_mode) != 0)) {
result = true;
}
return result;
}
bool FilePath::DeleteFile(const TString FileName) {
bool result = false;
if (FileExists(FileName) == true) {
if (unlink(StringToFileSystemString(FileName)) == 0) {
result = true;
}
}
return result;
}
bool FilePath::DeleteDirectory(const TString DirectoryName) {
bool result = false;
if (DirectoryExists(DirectoryName) == true) {
if (unlink(StringToFileSystemString(DirectoryName)) == 0) {
result = true;
}
}
return result;
}
TString FilePath::IncludeTrailingSeparator(const TString value) {
TString result = value;
if (value.size() > 0) {
TString::iterator i = result.end();
i--;
if (*i != TRAILING_PATHSEPARATOR) {
result += TRAILING_PATHSEPARATOR;
}
}
return result;
}
TString FilePath::IncludeTrailingSeparator(const char* value) {
TString lvalue = PlatformString(value).toString();
return IncludeTrailingSeparator(lvalue);
}
TString FilePath::IncludeTrailingSeparator(const wchar_t* value) {
TString lvalue = PlatformString(value).toString();
return IncludeTrailingSeparator(lvalue);
}
TString FilePath::ExtractFilePath(TString Path) {
return dirname(StringToFileSystemString(Path));
}
TString FilePath::ExtractFileExt(TString Path) {
TString result;
size_t dot = Path.find_last_of('.');
if (dot != TString::npos) {
result = Path.substr(dot, Path.size() - dot);
}
return result;
}
TString FilePath::ExtractFileName(TString Path) {
return basename(StringToFileSystemString(Path));
}
TString FilePath::ChangeFileExt(TString Path, TString Extension) {
TString result;
size_t dot = Path.find_last_of('.');
if (dot != TString::npos) {
result = Path.substr(0, dot) + Extension;
}
if (result.empty() == true) {
result = Path;
}
return result;
}
TString FilePath::FixPathForPlatform(TString Path) {
TString result = Path;
std::replace(result.begin(), result.end(),
BAD_TRAILING_PATHSEPARATOR, TRAILING_PATHSEPARATOR);
return result;
}
TString FilePath::FixPathSeparatorForPlatform(TString Path) {
TString result = Path;
std::replace(result.begin(), result.end(),
BAD_PATH_SEPARATOR, PATH_SEPARATOR);
return result;
}
TString FilePath::PathSeparator() {
TString result;
result = PATH_SEPARATOR;
return result;
}
bool FilePath::CreateDirectory(TString Path, bool ownerOnly) {
bool result = false;
std::list<TString> paths;
TString lpath = Path;
while (lpath.empty() == false && DirectoryExists(lpath) == false) {
paths.push_front(lpath);
lpath = ExtractFilePath(lpath);
}
for (std::list<TString>::iterator iterator = paths.begin();
iterator != paths.end(); iterator++) {
lpath = *iterator;
mode_t mode = S_IRWXU;
if (!ownerOnly) {
mode |= S_IRWXG | S_IROTH | S_IXOTH;
}
if (mkdir(StringToFileSystemString(lpath), mode) == 0) {
result = true;
} else {
result = false;
break;
}
}
return result;
}
void FilePath::ChangePermissions(TString FileName, bool ownerOnly) {
mode_t mode = S_IRWXU;
if (!ownerOnly) {
mode |= S_IRWXG | S_IROTH | S_IXOTH;
}
chmod(FileName.data(), mode);
}

View File

@ -1,313 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "PosixPlatform.h"
#include "PlatformString.h"
#include "FilePath.h"
#include "Helpers.h"
#include <assert.h>
#include <stdbool.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/file.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <errno.h>
#include <limits.h>
#include <pwd.h>
#include <iostream>
#include <algorithm>
#include <dlfcn.h>
#include <signal.h>
using namespace std;
PosixPlatform::PosixPlatform(void) {
}
PosixPlatform::~PosixPlatform(void) {
}
TString PosixPlatform::GetTempDirectory() {
struct passwd* pw = getpwuid(getuid());
TString homedir(pw->pw_dir);
homedir += getTmpDirString();
if (!FilePath::DirectoryExists(homedir)) {
if (!FilePath::CreateDirectory(homedir, false)) {
homedir.clear();
}
}
return homedir;
}
TString PosixPlatform::fixName(const TString& name) {
TString fixedName(name);
const TString chars("?:*<>/\\");
for (TString::const_iterator it = chars.begin(); it != chars.end(); it++) {
fixedName.erase(std::remove(fixedName.begin(),
fixedName.end(), *it), fixedName.end());
}
return fixedName;
}
MessageResponse PosixPlatform::ShowResponseMessage(TString title,
TString description) {
MessageResponse result = mrCancel;
printf("%s %s (Y/N)\n", PlatformString(title).toPlatformString(),
PlatformString(description).toPlatformString());
fflush(stdout);
std::string input;
std::cin >> input;
if (input == "Y") {
result = mrOK;
}
return result;
}
Module PosixPlatform::LoadLibrary(TString FileName) {
return dlopen(StringToFileSystemString(FileName), RTLD_LAZY);
}
void PosixPlatform::FreeLibrary(Module AModule) {
dlclose(AModule);
}
Procedure PosixPlatform::GetProcAddress(Module AModule,
std::string MethodName) {
return dlsym(AModule, PlatformString(MethodName));
}
Process* PosixPlatform::CreateProcess() {
return new PosixProcess();
}
void PosixPlatform::addPlatformDependencies(JavaLibrary *pJavaLibrary) {
}
void Platform::CopyString(char *Destination,
size_t NumberOfElements, const char *Source) {
strncpy(Destination, Source, NumberOfElements);
if (NumberOfElements > 0) {
Destination[NumberOfElements - 1] = '\0';
}
}
void Platform::CopyString(wchar_t *Destination,
size_t NumberOfElements, const wchar_t *Source) {
wcsncpy(Destination, Source, NumberOfElements);
if (NumberOfElements > 0) {
Destination[NumberOfElements - 1] = '\0';
}
}
// Owner must free the return value.
MultibyteString Platform::WideStringToMultibyteString(
const wchar_t* value) {
MultibyteString result;
size_t count = 0;
if (value == NULL) {
return result;
}
count = wcstombs(NULL, value, 0);
if (count > 0) {
result.data = new char[count + 1];
result.data[count] = '\0';
result.length = count;
wcstombs(result.data, value, count);
}
return result;
}
// Owner must free the return value.
WideString Platform::MultibyteStringToWideString(const char* value) {
WideString result;
size_t count = 0;
if (value == NULL) {
return result;
}
count = mbstowcs(NULL, value, 0);
if (count > 0) {
result.data = new wchar_t[count + 1];
result.data[count] = '\0';
result.length = count;
mbstowcs(result.data, value, count);
}
return result;
}
void PosixPlatform::InitStreamLocale(wios *stream) {
// Nothing to do for POSIX platforms.
}
PosixProcess::PosixProcess() : Process() {
FChildPID = 0;
FRunning = false;
FOutputHandle = 0;
FInputHandle = 0;
}
PosixProcess::~PosixProcess() {
Terminate();
}
bool PosixProcess::ReadOutput() {
bool result = false;
if (FOutputHandle != 0 && IsRunning() == true) {
char buffer[4096] = {0};
ssize_t count = read(FOutputHandle, buffer, sizeof (buffer));
if (count == -1) {
if (errno == EINTR) {
// continue;
} else {
perror("read");
exit(1);
}
} else if (count == 0) {
// break;
} else {
std::list<TString> output = Helpers::StringToArray(buffer);
FOutput.splice(FOutput.end(), output, output.begin(), output.end());
result = true;
}
}
return false;
}
bool PosixProcess::IsRunning() {
bool result = false;
if (kill(FChildPID, 0) == 0) {
result = true;
}
return result;
}
bool PosixProcess::Terminate() {
bool result = false;
if (IsRunning() == true && FRunning == true) {
FRunning = false;
Cleanup();
int status = kill(FChildPID, SIGTERM);
if (status == 0) {
result = true;
} else {
#ifdef DEBUG
if (errno == EINVAL) {
printf("Kill error: The value of the sig argument is an invalid or unsupported signal number.");
} else if (errno == EPERM) {
printf("Kill error: The process does not have permission to send the signal to any receiving process.");
} else if (errno == ESRCH) {
printf("Kill error: No process or process group can be found corresponding to that specified by pid.");
}
#endif // DEBUG
if (IsRunning() == true) {
status = kill(FChildPID, SIGKILL);
if (status == 0) {
result = true;
}
}
}
}
return result;
}
bool PosixProcess::Wait() {
bool result = false;
int status = 0;
pid_t wpid = 0;
wpid = wait(&status);
if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) {
if (errno != EINTR) {
status = -1;
}
}
#ifdef DEBUG
if (WIFEXITED(status)) {
printf("child exited, status=%d\n", WEXITSTATUS(status));
} else if (WIFSIGNALED(status)) {
printf("child killed (signal %d)\n", WTERMSIG(status));
} else if (WIFSTOPPED(status)) {
printf("child stopped (signal %d)\n", WSTOPSIG(status));
#ifdef WIFCONTINUED // Not all implementations support this
} else if (WIFCONTINUED(status)) {
printf("child continued\n");
#endif // WIFCONTINUED
} else { // Non-standard case -- may never happen
printf("Unexpected status (0x%x)\n", status);
}
#endif // DEBUG
if (wpid != -1) {
result = true;
}
return result;
}
TProcessID PosixProcess::GetProcessID() {
return FChildPID;
}
void PosixProcess::SetInput(TString Value) {
if (FInputHandle != 0) {
if (write(FInputHandle, Value.data(), Value.size()) < 0) {
throw Exception(_T("Internal Error - write failed"));
}
}
}
std::list<TString> PosixProcess::GetOutput() {
ReadOutput();
return Process::GetOutput();
}

View File

@ -1,83 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef POSIXPLATFORM_H
#define POSIXPLATFORM_H
#include "Platform.h"
#include <signal.h>
class PosixPlatform : virtual public Platform {
protected:
TString fixName(const TString& name);
virtual TString getTmpDirString() = 0;
public:
PosixPlatform(void);
virtual ~PosixPlatform(void);
public:
virtual MessageResponse ShowResponseMessage(TString title,
TString description);
virtual Module LoadLibrary(TString FileName);
virtual void FreeLibrary(Module AModule);
virtual Procedure GetProcAddress(Module AModule, std::string MethodName);
virtual Process* CreateProcess();
virtual TString GetTempDirectory();
void InitStreamLocale(wios *stream);
void addPlatformDependencies(JavaLibrary *pJavaLibrary);
};
class PosixProcess : public Process {
private:
pid_t FChildPID;
sigset_t saveblock;
int FOutputHandle;
int FInputHandle;
struct sigaction savintr, savequit;
bool FRunning;
void Cleanup();
bool ReadOutput();
public:
PosixProcess();
virtual ~PosixProcess();
virtual bool IsRunning();
virtual bool Terminate();
virtual bool Execute(const TString Application,
const std::vector<TString> Arguments, bool AWait = false);
virtual bool Wait();
virtual TProcessID GetProcessID();
virtual void SetInput(TString Value);
virtual std::list<TString> GetOutput();
};
#endif // POSIXPLATFORM_H

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -64,8 +64,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
"jdk.incubator.jpackage.internal.resources.WinResources"); "jdk.incubator.jpackage.internal.resources.WinResources");
private final static String LIBRARY_NAME = "applauncher.dll"; private final static String LIBRARY_NAME = "applauncher.dll";
private final static String REDIST_MSVCR = "vcruntimeVS_VER.dll";
private final static String REDIST_MSVCP = "msvcpVS_VER.dll";
private final static String TEMPLATE_APP_ICON ="java48.ico"; private final static String TEMPLATE_APP_ICON ="java48.ico";
@ -189,13 +187,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
// copy the jars // copy the jars
copyApplication(params); copyApplication(params);
// copy in the needed libraries
try (InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
Files.copy(is_lib, binDir.resolve(LIBRARY_NAME));
}
copyMSVCDLLs();
// create the additional launcher(s), if any // create the additional launcher(s), if any
List<Map<String, ? super Object>> entryPoints = List<Map<String, ? super Object>> entryPoints =
StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params); StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
@ -209,27 +200,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
public void prepareJreFiles(Map<String, ? super Object> params) public void prepareJreFiles(Map<String, ? super Object> params)
throws IOException {} throws IOException {}
private void copyMSVCDLLs() throws IOException {
AtomicReference<IOException> ioe = new AtomicReference<>();
try (Stream<Path> files = Files.list(runtimeDir.resolve("bin"))) {
files.filter(p -> Pattern.matches(
"^(vcruntime|msvcp|msvcr|ucrtbase|api-ms-win-).*\\.dll$",
p.toFile().getName().toLowerCase()))
.forEach(p -> {
try {
Files.copy(p, binDir.resolve((p.toFile().getName())));
} catch (IOException e) {
ioe.set(e);
}
});
}
IOException e = ioe.get();
if (e != null) {
throw e;
}
}
private void validateValueAndPut( private void validateValueAndPut(
Map<String, String> data, String key, Map<String, String> data, String key,
BundlerParamInfo<String> param, BundlerParamInfo<String> param,

View File

@ -0,0 +1,175 @@
/*
* Copyright (c) 2020, 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 <io.h>
#include <fcntl.h>
#include <windows.h>
#include "AppLauncher.h"
#include "Log.h"
#include "FileUtils.h"
#include "UniqueHandle.h"
#include "ErrorHandling.h"
#include "WinErrorHandling.h"
// AllowSetForegroundWindow
#pragma comment(lib, "user32")
namespace {
void launchApp() {
// [RT-31061] otherwise UI can be left in back of other windows.
::AllowSetForegroundWindow(ASFW_ANY);
const tstring launcherPath = SysInfo::getProcessModulePath();
const tstring appImageRoot = FileUtils::dirname(launcherPath);
AppLauncher()
.setImageRoot(appImageRoot)
.addJvmLibName(_T("bin\\jli.dll"))
.setAppDir(FileUtils::mkpath() << appImageRoot << _T("app"))
.setDefaultRuntimePath(FileUtils::mkpath() << appImageRoot
<< _T("runtime"))
.launch();
}
} // namespace
#ifndef JP_LAUNCHERW
int APIENTRY wmain() {
return AppLauncher::launch(std::nothrow, launchApp);
}
#else
namespace {
class LastErrorGuiLogAppender : public LogAppender {
public:
virtual void append(const LogEvent& v) {
JP_TRY;
const std::wstring msg = (tstrings::any()
<< AppLauncher::lastErrorMsg()).wstr();
MessageBox(0, msg.c_str(),
FileUtils::basename(SysInfo::getProcessModulePath()).c_str(),
MB_ICONERROR | MB_OK);
JP_CATCH_ALL;
}
};
class Console {
public:
Console() {
if (!AttachConsole(ATTACH_PARENT_PROCESS)) {
// Failed to connect to parent's console. Create our own.
if (!AllocConsole()) {
// We already have a console, no need to redirect std I/O.
return;
}
}
stdoutChannel = std::unique_ptr<Channel>(new Channel(stdout));
stderrChannel = std::unique_ptr<Channel>(new Channel(stderr));
}
struct FileCloser {
typedef FILE* pointer;
void operator()(pointer h) {
::fclose(h);
}
};
typedef std::unique_ptr<
FileCloser::pointer,
FileCloser
> UniqueFILEHandle;
private:
class Channel {
public:
Channel(FILE* stdFILEHandle): stdFILEHandle(stdFILEHandle) {
const char* stdFileName = "CONOUT$";
const char* openMode = "w";
if (stdFILEHandle == stdin) {
stdFileName = "CONIN$";
openMode = "r";
}
FILE* fp = 0;
freopen_s(&fp, stdFileName, openMode, stdFILEHandle);
fileHandle = UniqueFILEHandle(fp);
std::ios_base::sync_with_stdio();
}
virtual ~Channel() {
JP_TRY;
FILE* fp = 0;
fileHandle = UniqueFILEHandle(fp);
std::ios_base::sync_with_stdio();
JP_CATCH_ALL;
}
private:
UniqueFILEHandle fileHandle;
FILE *stdFILEHandle;
};
std::unique_ptr<Channel> stdoutChannel;
std::unique_ptr<Channel> stderrChannel;
};
void launchAppW() {
std::unique_ptr<Console> console;
if (AppLauncher::isWithLogging()) {
console = std::unique_ptr<Console>(new Console());
}
launchApp();
}
} // namespace
int APIENTRY wWinMain(HINSTANCE, HINSTANCE, LPWSTR, int) {
LastErrorGuiLogAppender lastErrorLogAppender;
TeeLogAppender logAppender(&AppLauncher::defaultLastErrorLogAppender(),
&lastErrorLogAppender);
return AppLauncher::launch(std::nothrow, launchAppW, &logAppender);
}
#endif

View File

@ -0,0 +1,90 @@
/*
* Copyright (c) 2020, 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 <cstring>
#include "PlatformLogEvent.h"
#include "FileUtils.h"
#include "Log.h"
namespace {
tstring retrieveModuleName() {
try {
return FileUtils::basename(SysInfo::getCurrentModulePath());
}
catch (const std::runtime_error&) {
return _T("Unknown");
}
}
TCHAR moduleName[MAX_PATH] = { 'U', 'n', 'k', 'n', 'o', 'w', 'n', TCHAR(0) };
const LPCTSTR formatStr = _T("%04u/%02u/%02u %02u:%02u:%02u.%03u, %s (PID: %u, TID: %u), ");
} // namespace
PlatformLogEvent::PlatformLogEvent() {
std::memset(static_cast<void*>(this), 0, sizeof(*this));
}
void LogEvent::init(PlatformLogEvent& logEvent) {
GetLocalTime(&logEvent.ts);
logEvent.pid = GetCurrentProcessId();
logEvent.tid = GetCurrentThreadId();
logEvent.moduleName = ::moduleName;
}
void LogEvent::appendFormatted(const PlatformLogEvent& logEvent,
tstring& buffer) {
const tstring str = tstrings::unsafe_format(formatStr,
unsigned(logEvent.ts.wYear),
unsigned(logEvent.ts.wMonth),
unsigned(logEvent.ts.wDay),
unsigned(logEvent.ts.wHour),
unsigned(logEvent.ts.wMinute),
unsigned(logEvent.ts.wSecond),
unsigned(logEvent.ts.wMilliseconds),
logEvent.moduleName,
logEvent.pid,
logEvent.tid);
buffer.append(str);
}
void Logger::initializingLogging() {
moduleName[0] = TCHAR(0);
}
void Logger::initializeLogging() {
tstring mname = retrieveModuleName();
mname.resize(_countof(moduleName) - 1);
std::memcpy(moduleName, mname.c_str(), mname.size());
moduleName[mname.size()] = TCHAR(0);
}

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,32 +23,19 @@
* questions. * questions.
*/ */
#ifndef FILEATTRIBUTES_H #ifndef PlatformLogEvent_h
#define FILEATTRIBUTES_H #define PlatformLogEvent_h
#include "Platform.h" #include <windows.h>
#include "PlatformString.h"
#include "FileAttribute.h"
#include <vector>
class FileAttributes { struct PlatformLogEvent {
private: SYSTEMTIME ts;
TString FFileName; long tid;
bool FFollowLink; long pid;
std::vector<FileAttribute> FAttributes; LPCTSTR moduleName;
bool WriteAttributes(); PlatformLogEvent();
bool ReadAttributes();
bool Valid(const FileAttribute Value);
public:
FileAttributes(const TString FileName, bool FollowLink = true);
void Append(const FileAttribute Value);
bool Contains(const FileAttribute Value);
void Remove(const FileAttribute Value);
}; };
#endif // FILEATTRIBUTES_H #endif // PlatformLogEvent_h

View File

@ -0,0 +1,80 @@
/*
* Copyright (c) 2020, 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 "Dll.h"
#include "SysInfo.h"
#include "FileUtils.h"
#include "WinSysInfo.h"
#include "WinErrorHandling.h"
namespace {
Dll::Handle loadLibrary(const std::wstring& path) {
HMODULE h = LoadLibraryW(path.c_str());
if (!h) {
JP_THROW(SysError(tstrings::any() << "LoadLibraryW(" <<
path << ") failed", LoadLibraryW));
}
return Dll::Handle(h);
}
} // namesace
Dll::Dll(const tstrings::any &libPath): thePath(libPath.tstr()),
handle(loadLibrary(libPath.wstr())) {
}
Dll::Dll(const tstrings::any &libName, const System &tag):
thePath(FileUtils::combinePath(SysInfo::getSystem32Dir(),
libName.tstr())),
handle(loadLibrary(tstrings::any(thePath).wstr())) {
}
Dll::Dll(const Dll& other): thePath(other.thePath) {
HMODULE h = NULL;
if (!GetModuleHandleExW(0, thePath.c_str(), &h)) {
JP_THROW(SysError(tstrings::any() << "GetModuleHandleExW("
<< thePath << ") failed", GetModuleHandleExW));
}
handle = Handle(h);
}
void* Dll::getFunction(const std::string &name, bool throwIfNotFound) const {
void *ptr = GetProcAddress(handle.get(), name.c_str());
if (throwIfNotFound && ptr == NULL) {
JP_THROW(SysError(tstrings::any() << "GetProcAddress(" << thePath
<< ", " << name << ") failed", GetProcAddress));
}
return ptr;
}
/*static*/
void Dll::freeLibrary(HMODULE h) {
if (h) {
FreeLibrary(h);
}
}

View File

@ -104,9 +104,8 @@ std::wstring getSystemMessageDescription(DWORD messageId, HMODULE moduleHandle)
SysError::SysError(const tstrings::any& msg, const void* caller, DWORD ec, SysError::SysError(const tstrings::any& msg, const void* caller, DWORD ec,
const char* label): const char* label):
std::runtime_error(makeMessage(msg.str(), label, caller, ec)) {
std::runtime_error(makeMessage(msg.str(), label, caller, ec)) {
} }
std::wstring SysError::getSysErrorMessage(DWORD errCode, HMODULE moduleHandle) { std::wstring SysError::getSysErrorMessage(DWORD errCode, HMODULE moduleHandle) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -26,8 +26,11 @@
#include <memory> #include <memory>
#include <algorithm> #include <algorithm>
#include <shlwapi.h> #include <shlwapi.h>
#include <stdlib.h>
#include <direct.h>
#include "FileUtils.h" #include "FileUtils.h"
#include "WinFileUtils.h"
#include "WinErrorHandling.h" #include "WinErrorHandling.h"
#include "Log.h" #include "Log.h"
@ -40,7 +43,6 @@ namespace FileUtils {
namespace { namespace {
tstring reservedFilenameChars() { tstring reservedFilenameChars() {
tstring buf; tstring buf;
for (char charCode = 0; charCode < 32; ++charCode) { for (char charCode = 0; charCode < 32; ++charCode) {
@ -52,10 +54,6 @@ tstring reservedFilenameChars() {
} // namespace } // namespace
bool isDirSeparator(const tstring::value_type c) {
return (c == '/' || c == '\\');
}
bool isFileExists(const tstring &filePath) { bool isFileExists(const tstring &filePath) {
return GetFileAttributes(filePath.c_str()) != INVALID_FILE_ATTRIBUTES; return GetFileAttributes(filePath.c_str()) != INVALID_FILE_ATTRIBUTES;
} }
@ -78,73 +76,32 @@ bool isDirectoryNotEmpty(const tstring &dirPath) {
return FALSE == PathIsDirectoryEmpty(dirPath.c_str()); return FALSE == PathIsDirectoryEmpty(dirPath.c_str());
} }
tstring dirname(const tstring &path) {
tstring::size_type pos = path.find_last_of(_T("\\/"));
if (pos != tstring::npos) {
pos = path.find_last_not_of(_T("\\/"), pos); // skip trailing slashes
}
return pos == tstring::npos ? tstring() : path.substr(0, pos + 1);
}
tstring basename(const tstring &path) { tstring toAbsolutePath(const tstring& path) {
const tstring::size_type pos = path.find_last_of(_T("\\/"));
if (pos == tstring::npos) {
return path;
}
return path.substr(pos + 1);
}
tstring suffix(const tstring &path) {
const tstring::size_type pos = path.rfind('.');
if (pos == tstring::npos) {
return tstring();
}
const tstring::size_type dirSepPos = path.find_first_of(_T("\\/"),
pos + 1);
if (dirSepPos != tstring::npos) {
return tstring();
}
// test for '/..' and '..' cases
if (pos != 0 && path[pos - 1] == '.'
&& (pos == 1 || isDirSeparator(path[pos - 2]))) {
return tstring();
}
return path.substr(pos);
}
tstring combinePath(const tstring& parent, const tstring& child) {
if (parent.empty()) {
return child;
}
if (child.empty()) {
return parent;
}
tstring parentWOSlash = removeTrailingSlash(parent);
// also handle the case when child contains starting slash
bool childHasSlash = isDirSeparator(child.front());
tstring childWOSlash = childHasSlash ? child.substr(1) : child;
return parentWOSlash + _T("\\") + childWOSlash;
}
tstring removeTrailingSlash(const tstring& path) {
if (path.empty()) { if (path.empty()) {
return path; TCHAR* buf = _tgetcwd(0, 1);
} if (buf) {
tstring::const_reverse_iterator it = path.rbegin(); const tstring result(buf);
tstring::const_reverse_iterator end = path.rend(); free(buf);
if (result.empty()) {
JP_THROW(tstrings::any() << "_tgetcwd() returned empty string");
}
return result;
}
while (it != end && isDirSeparator(*it)) { JP_THROW(tstrings::any() << "_tgetcwd() failed");
++it;
} }
return path.substr(0, end - it);
TCHAR* buf = _tfullpath(0, path.c_str(), size_t(1));
if (buf) {
const tstring result(buf);
free(buf);
return result;
}
JP_THROW(tstrings::any() << "_tfullpath(" << path << ") failed");
} }
tstring normalizePath(tstring v) {
std::replace(v.begin(), v.end(), '/', '\\');
return tstrings::toLower(v);
}
namespace { namespace {
@ -565,11 +522,6 @@ void iterateDirectory(const tstring &dirPath, DirectoryCallback& callback)
} }
tstring replaceSuffix(const tstring& path, const tstring& newSuffix) {
return (path.substr(0, path.size() - suffix(path).size()) + newSuffix);
}
DirectoryIterator& DirectoryIterator::findItems(tstring_array& v) { DirectoryIterator& DirectoryIterator::findItems(tstring_array& v) {
if (!isDirectory(root)) { if (!isDirectory(root)) {
return *this; return *this;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -23,8 +23,8 @@
* questions. * questions.
*/ */
#ifndef FILEUTILS_H #ifndef WINFILEUTILS_H
#define FILEUTILS_H #define WINFILEUTILS_H
#include <fstream> #include <fstream>
@ -33,48 +33,6 @@
namespace FileUtils { namespace FileUtils {
// Returns 'true' if the given character is a path separator.
bool isDirSeparator(const tstring::value_type c);
// checks if the file or directory exists
bool isFileExists(const tstring &filePath);
// checks is the specified file is a directory
// returns false if the path does not exist
bool isDirectory(const tstring &filePath);
// checks if the specified directory is not empty
// returns true if the path is an existing directory and
// it contains at least one file other than "." or "..".
bool isDirectoryNotEmpty(const tstring &dirPath);
// returns directory part of the path.
// returns empty string if the path contains only filename.
// if the path ends with slash/backslash,
// returns removeTrailingSlashes(path).
tstring dirname(const tstring &path);
// returns basename part of the path
// if the path ends with slash/backslash, returns empty string.
tstring basename(const tstring &path);
/**
* Translates forward slashes to back slashes and returns lower case version
* of the given string.
*/
tstring normalizePath(tstring v);
// Returns suffix of the path. If the given path has a suffix the first
// character of the return value is '.'.
// Otherwise return value if empty string.
tstring suffix(const tstring &path);
// combines two strings into a path
tstring combinePath(const tstring& parent, const tstring& child);
// removes trailing slashes and backslashes in the path if any
tstring removeTrailingSlash(const tstring& path);
// Creates a file with unique name in the specified base directory, // Creates a file with unique name in the specified base directory,
// throws an exception if operation fails // throws an exception if operation fails
// path is constructed as <prefix><random number><suffix>. // path is constructed as <prefix><random number><suffix>.
@ -166,14 +124,6 @@ namespace FileUtils {
// the given directory. // the given directory.
void iterateDirectory(const tstring &dirPath, DirectoryCallback& callback); void iterateDirectory(const tstring &dirPath, DirectoryCallback& callback);
/**
* Replace file suffix, example replaceSuffix("file/path.txt", ".csv")
* @param path file path to replace suffix
* @param suffix new suffix for path
* @return return file path with new suffix
*/
tstring replaceSuffix(const tstring& path, const tstring& suffix=tstring());
class DirectoryIterator: DirectoryCallback { class DirectoryIterator: DirectoryCallback {
public: public:
DirectoryIterator(const tstring& root=tstring()): root(root) { DirectoryIterator(const tstring& root=tstring()): root(root) {
@ -225,34 +175,6 @@ namespace FileUtils {
return DirectoryIterator(basedir).findItems(); return DirectoryIterator(basedir).findItems();
} }
// Helper to construct path from multiple components.
//
// Sample usage:
// Construct "c:\Program Files\Java" string from three components
//
// tstring path = FileUtils::mkpath() << _T("c:")
// << _T("Program Files")
// << _T("Java");
//
class mkpath {
public:
operator const tstring& () const {
return path;
}
mkpath& operator << (const tstring& p) {
path = combinePath(path, p);
return *this;
}
// mimic std::string
const tstring::value_type* c_str() const {
return path.c_str();
}
private:
tstring path;
};
struct Directory { struct Directory {
Directory() { Directory() {
} }
@ -395,4 +317,4 @@ namespace FileUtils {
}; };
} // FileUtils } // FileUtils
#endif // FILEUTILS_H #endif // WINFILEUTILS_H

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -97,7 +97,7 @@ tstring getModulePath(HMODULE h)
} // namespace } // namespace
tstring getProcessModulePath() { tstring getProcessModulePath() {
return getModulePath(NULL); return FileUtils::toAbsolutePath(getModulePath(NULL));
} }
HMODULE getCurrentModuleHandle() HMODULE getCurrentModuleHandle()

View File

@ -1,98 +0,0 @@
/*
* Copyright (c) 2012, 2019, 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 <Windows.h>
#include <Shellapi.h>
#include <locale.h>
#include <tchar.h>
#include <string>
#define JPACKAGE_LIBRARY TEXT("applauncher.dll")
typedef bool (*start_launcher)(int argc, TCHAR* argv[]);
typedef void (*stop_launcher)();
std::wstring GetTitle() {
std::wstring result;
wchar_t buffer[MAX_PATH];
GetModuleFileName(NULL, buffer, MAX_PATH - 1);
buffer[MAX_PATH - 1] = '\0';
result = buffer;
size_t slash = result.find_last_of('\\');
if (slash != std::wstring::npos)
result = result.substr(slash + 1, result.size() - slash - 1);
return result;
}
#ifdef LAUNCHERC
int main(int argc0, char *argv0[]) {
#else // LAUNCHERC
int APIENTRY _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPTSTR lpCmdLine, int nCmdShow) {
#endif // LAUNCHERC
int result = 1;
TCHAR **argv;
int argc;
// [RT-31061] otherwise UI can be left in back of other windows.
::AllowSetForegroundWindow(ASFW_ANY);
::setlocale(LC_ALL, "en_US.utf8");
argv = CommandLineToArgvW(GetCommandLine(), &argc);
HMODULE library = ::LoadLibrary(JPACKAGE_LIBRARY);
if (library == NULL) {
std::wstring title = GetTitle();
std::wstring description = std::wstring(JPACKAGE_LIBRARY)
+ std::wstring(TEXT(" not found."));
MessageBox(NULL, description.data(),
title.data(), MB_ICONERROR | MB_OK);
}
else {
start_launcher start =
(start_launcher)GetProcAddress(library, "start_launcher");
stop_launcher stop =
(stop_launcher)GetProcAddress(library, "stop_launcher");
if (start != NULL && stop != NULL) {
if (start(argc, argv) == true) {
result = 0;
stop();
}
}
::FreeLibrary(library);
}
if (argv != NULL) {
LocalFree(argv);
}
return result;
}

View File

@ -1,48 +0,0 @@
/*
* Copyright (c) 2019, 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.
*/
#ifndef FILEATTRIBUTE_H
#define FILEATTRIBUTE_H
enum FileAttribute {
faArchive = FILE_ATTRIBUTE_ARCHIVE,
faCompressed = FILE_ATTRIBUTE_COMPRESSED,
faDevice = FILE_ATTRIBUTE_DEVICE,
faDirectory = FILE_ATTRIBUTE_DIRECTORY,
faEncrypted = FILE_ATTRIBUTE_ENCRYPTED,
faHidden = FILE_ATTRIBUTE_HIDDEN,
faNormal = FILE_ATTRIBUTE_NORMAL,
faNotContentIndexed = FILE_ATTRIBUTE_NOT_CONTENT_INDEXED,
faOffline = FILE_ATTRIBUTE_OFFLINE,
faSystem = FILE_ATTRIBUTE_SYSTEM,
faSymbolicLink = FILE_ATTRIBUTE_REPARSE_POINT,
faSparceFile = FILE_ATTRIBUTE_SPARSE_FILE,
faReadOnly = FILE_ATTRIBUTE_READONLY,
faTemporary = FILE_ATTRIBUTE_TEMPORARY,
faVirtual = FILE_ATTRIBUTE_VIRTUAL
};
#endif // FILEATTRIBUTE_H

View File

@ -1,468 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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 "FilePath.h"
#include <algorithm>
#include <list>
#include <ShellAPI.h>
bool FilePath::FileExists(const TString FileName) {
bool result = false;
WIN32_FIND_DATA FindFileData;
TString fileName = FixPathForPlatform(FileName);
HANDLE handle = FindFirstFile(fileName.data(), &FindFileData);
if (handle != INVALID_HANDLE_VALUE) {
if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
result = true;
}
else {
result = true;
}
FindClose(handle);
}
return result;
}
bool FilePath::DirectoryExists(const TString DirectoryName) {
bool result = false;
WIN32_FIND_DATA FindFileData;
TString directoryName = FixPathForPlatform(DirectoryName);
HANDLE handle = FindFirstFile(directoryName.data(), &FindFileData);
if (handle != INVALID_HANDLE_VALUE) {
if (FILE_ATTRIBUTE_DIRECTORY & FindFileData.dwFileAttributes) {
result = true;
}
FindClose(handle);
}
return result;
}
std::string GetLastErrorAsString() {
// Get the error message, if any.
DWORD errorMessageID = ::GetLastError();
if (errorMessageID == 0) {
return "No error message has been recorded";
}
LPSTR messageBuffer = NULL;
size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL,
SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
std::string message(messageBuffer, size);
// Free the buffer.
LocalFree(messageBuffer);
return message;
}
bool FilePath::DeleteFile(const TString FileName) {
bool result = false;
if (FileExists(FileName) == true) {
TString lFileName = FixPathForPlatform(FileName);
FileAttributes attributes(lFileName);
if (attributes.Contains(faReadOnly) == true) {
attributes.Remove(faReadOnly);
}
result = ::DeleteFile(lFileName.data()) == TRUE;
}
return result;
}
bool FilePath::DeleteDirectory(const TString DirectoryName) {
bool result = false;
if (DirectoryExists(DirectoryName) == true) {
SHFILEOPSTRUCTW fos = {0};
TString directoryName = FixPathForPlatform(DirectoryName);
DynamicBuffer<TCHAR> lDirectoryName(directoryName.size() + 2);
if (lDirectoryName.GetData() == NULL) {
return false;
}
memcpy(lDirectoryName.GetData(), directoryName.data(),
(directoryName.size() + 2) * sizeof(TCHAR));
lDirectoryName[directoryName.size() + 1] = NULL;
// Double null terminate for SHFileOperation.
// Delete the folder and everything inside.
fos.wFunc = FO_DELETE;
fos.pFrom = lDirectoryName.GetData();
fos.fFlags = FOF_NO_UI;
result = SHFileOperation(&fos) == 0;
}
return result;
}
TString FilePath::IncludeTrailingSeparator(const TString value) {
TString result = value;
if (value.size() > 0) {
TString::iterator i = result.end();
i--;
if (*i != TRAILING_PATHSEPARATOR) {
result += TRAILING_PATHSEPARATOR;
}
}
return result;
}
TString FilePath::IncludeTrailingSeparator(const char* value) {
TString lvalue = PlatformString(value).toString();
return IncludeTrailingSeparator(lvalue);
}
TString FilePath::IncludeTrailingSeparator(const wchar_t* value) {
TString lvalue = PlatformString(value).toString();
return IncludeTrailingSeparator(lvalue);
}
TString FilePath::ExtractFilePath(TString Path) {
TString result;
size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
if (slash != TString::npos)
result = Path.substr(0, slash);
return result;
}
TString FilePath::ExtractFileExt(TString Path) {
TString result;
size_t dot = Path.find_last_of('.');
if (dot != TString::npos) {
result = Path.substr(dot, Path.size() - dot);
}
return result;
}
TString FilePath::ExtractFileName(TString Path) {
TString result;
size_t slash = Path.find_last_of(TRAILING_PATHSEPARATOR);
if (slash != TString::npos)
result = Path.substr(slash + 1, Path.size() - slash - 1);
return result;
}
TString FilePath::ChangeFileExt(TString Path, TString Extension) {
TString result;
size_t dot = Path.find_last_of('.');
if (dot != TString::npos) {
result = Path.substr(0, dot) + Extension;
}
if (result.empty() == true) {
result = Path;
}
return result;
}
TString FilePath::FixPathForPlatform(TString Path) {
TString result = Path;
std::replace(result.begin(), result.end(),
BAD_TRAILING_PATHSEPARATOR, TRAILING_PATHSEPARATOR);
// The maximum path that does not require long path prefix. On Windows the
// maximum path is 260 minus 1 (NUL) but for directories it is 260 minus
// 12 minus 1 (to allow for the creation of a 8.3 file in the directory).
const int maxPath = 247;
if (result.length() > maxPath &&
result.find(_T("\\\\?\\")) == TString::npos &&
result.find(_T("\\\\?\\UNC")) == TString::npos) {
const TString prefix(_T("\\\\"));
if (!result.compare(0, prefix.size(), prefix)) {
// UNC path, converting to UNC path in long notation
result = _T("\\\\?\\UNC") + result.substr(1, result.length());
} else {
// converting to non-UNC path in long notation
result = _T("\\\\?\\") + result;
}
}
return result;
}
TString FilePath::FixPathSeparatorForPlatform(TString Path) {
TString result = Path;
std::replace(result.begin(), result.end(),
BAD_PATH_SEPARATOR, PATH_SEPARATOR);
return result;
}
TString FilePath::PathSeparator() {
TString result;
result = PATH_SEPARATOR;
return result;
}
bool FilePath::CreateDirectory(TString Path, bool ownerOnly) {
bool result = false;
std::list<TString> paths;
TString lpath = Path;
while (lpath.empty() == false && DirectoryExists(lpath) == false) {
paths.push_front(lpath);
lpath = ExtractFilePath(lpath);
}
for (std::list<TString>::iterator iterator = paths.begin();
iterator != paths.end(); iterator++) {
lpath = *iterator;
if (_wmkdir(lpath.data()) == 0) {
result = true;
} else {
result = false;
break;
}
}
return result;
}
void FilePath::ChangePermissions(TString FileName, bool ownerOnly) {
}
#include <algorithm>
FileAttributes::FileAttributes(const TString FileName, bool FollowLink) {
FFileName = FileName;
FFollowLink = FollowLink;
ReadAttributes();
}
bool FileAttributes::WriteAttributes() {
bool result = false;
DWORD attributes = 0;
for (std::vector<FileAttribute>::const_iterator iterator =
FAttributes.begin();
iterator != FAttributes.end(); iterator++) {
switch (*iterator) {
case faArchive: {
attributes = attributes & FILE_ATTRIBUTE_ARCHIVE;
break;
}
case faCompressed: {
attributes = attributes & FILE_ATTRIBUTE_COMPRESSED;
break;
}
case faDevice: {
attributes = attributes & FILE_ATTRIBUTE_DEVICE;
break;
}
case faDirectory: {
attributes = attributes & FILE_ATTRIBUTE_DIRECTORY;
break;
}
case faEncrypted: {
attributes = attributes & FILE_ATTRIBUTE_ENCRYPTED;
break;
}
case faHidden: {
attributes = attributes & FILE_ATTRIBUTE_HIDDEN;
break;
}
case faNormal: {
attributes = attributes & FILE_ATTRIBUTE_NORMAL;
break;
}
case faNotContentIndexed: {
attributes = attributes & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED;
break;
}
case faOffline: {
attributes = attributes & FILE_ATTRIBUTE_OFFLINE;
break;
}
case faSystem: {
attributes = attributes & FILE_ATTRIBUTE_SYSTEM;
break;
}
case faSymbolicLink: {
attributes = attributes & FILE_ATTRIBUTE_REPARSE_POINT;
break;
}
case faSparceFile: {
attributes = attributes & FILE_ATTRIBUTE_SPARSE_FILE;
break;
}
case faReadOnly: {
attributes = attributes & FILE_ATTRIBUTE_READONLY;
break;
}
case faTemporary: {
attributes = attributes & FILE_ATTRIBUTE_TEMPORARY;
break;
}
case faVirtual: {
attributes = attributes & FILE_ATTRIBUTE_VIRTUAL;
break;
}
}
}
if (::SetFileAttributes(FFileName.data(), attributes) != 0) {
result = true;
}
return result;
}
#define S_ISRUSR(m) (((m) & S_IRWXU) == S_IRUSR)
#define S_ISWUSR(m) (((m) & S_IRWXU) == S_IWUSR)
#define S_ISXUSR(m) (((m) & S_IRWXU) == S_IXUSR)
#define S_ISRGRP(m) (((m) & S_IRWXG) == S_IRGRP)
#define S_ISWGRP(m) (((m) & S_IRWXG) == S_IWGRP)
#define S_ISXGRP(m) (((m) & S_IRWXG) == S_IXGRP)
#define S_ISROTH(m) (((m) & S_IRWXO) == S_IROTH)
#define S_ISWOTH(m) (((m) & S_IRWXO) == S_IWOTH)
#define S_ISXOTH(m) (((m) & S_IRWXO) == S_IXOTH)
bool FileAttributes::ReadAttributes() {
bool result = false;
DWORD attributes = ::GetFileAttributes(FFileName.data());
if (attributes != INVALID_FILE_ATTRIBUTES) {
result = true;
if (attributes | FILE_ATTRIBUTE_ARCHIVE) {
FAttributes.push_back(faArchive);
}
if (attributes | FILE_ATTRIBUTE_COMPRESSED) {
FAttributes.push_back(faCompressed);
}
if (attributes | FILE_ATTRIBUTE_DEVICE) {
FAttributes.push_back(faDevice);
}
if (attributes | FILE_ATTRIBUTE_DIRECTORY) {
FAttributes.push_back(faDirectory);
}
if (attributes | FILE_ATTRIBUTE_ENCRYPTED) {
FAttributes.push_back(faEncrypted);
}
if (attributes | FILE_ATTRIBUTE_HIDDEN) {
FAttributes.push_back(faHidden);
}
if (attributes | FILE_ATTRIBUTE_NORMAL) {
FAttributes.push_back(faNormal);
}
if (attributes | FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) {
FAttributes.push_back(faNotContentIndexed);
}
if (attributes | FILE_ATTRIBUTE_SYSTEM) {
FAttributes.push_back(faSystem);
}
if (attributes | FILE_ATTRIBUTE_OFFLINE) {
FAttributes.push_back(faOffline);
}
if (attributes | FILE_ATTRIBUTE_REPARSE_POINT) {
FAttributes.push_back(faSymbolicLink);
}
if (attributes | FILE_ATTRIBUTE_SPARSE_FILE) {
FAttributes.push_back(faSparceFile);
}
if (attributes | FILE_ATTRIBUTE_READONLY ) {
FAttributes.push_back(faReadOnly);
}
if (attributes | FILE_ATTRIBUTE_TEMPORARY) {
FAttributes.push_back(faTemporary);
}
if (attributes | FILE_ATTRIBUTE_VIRTUAL) {
FAttributes.push_back(faVirtual);
}
}
return result;
}
bool FileAttributes::Valid(const FileAttribute Value) {
bool result = false;
switch (Value) {
case faHidden:
case faReadOnly: {
result = true;
break;
}
default:
break;
}
return result;
}
void FileAttributes::Append(FileAttribute Value) {
if (Valid(Value) == true) {
FAttributes.push_back(Value);
WriteAttributes();
}
}
bool FileAttributes::Contains(FileAttribute Value) {
bool result = false;
std::vector<FileAttribute>::const_iterator iterator =
std::find(FAttributes.begin(), FAttributes.end(), Value);
if (iterator != FAttributes.end()) {
result = true;
}
return result;
}
void FileAttributes::Remove(FileAttribute Value) {
if (Valid(Value) == true) {
std::vector<FileAttribute>::iterator iterator =
std::find(FAttributes.begin(), FAttributes.end(), Value);
if (iterator != FAttributes.end()) {
FAttributes.erase(iterator);
WriteAttributes();
}
}
}

View File

@ -1,765 +0,0 @@
/*
* Copyright (c) 2014, 2020, 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 "Platform.h"
#include "JavaVirtualMachine.h"
#include "WindowsPlatform.h"
#include "Package.h"
#include "Helpers.h"
#include "PlatformString.h"
#include "Macros.h"
#include <map>
#include <vector>
#include <regex>
#include <fstream>
#include <locale>
#include <codecvt>
using namespace std;
#define WINDOWS_JPACKAGE_TMP_DIR \
L"\\AppData\\Local\\Java\\JPackage\\tmp"
class Registry {
private:
HKEY FKey;
HKEY FOpenKey;
bool FOpen;
public:
Registry(HKEY Key) {
FOpen = false;
FKey = Key;
}
~Registry() {
Close();
}
void Close() {
if (FOpen == true) {
RegCloseKey(FOpenKey);
}
}
bool Open(TString SubKey) {
bool result = false;
Close();
if (RegOpenKeyEx(FKey, SubKey.data(), 0, KEY_READ, &FOpenKey) ==
ERROR_SUCCESS) {
result = true;
}
return result;
}
std::list<TString> GetKeys() {
std::list<TString> result;
DWORD count;
if (RegQueryInfoKey(FOpenKey, NULL, NULL, NULL, NULL, NULL, NULL,
&count, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) {
DWORD length = 255;
DynamicBuffer<TCHAR> buffer(length);
if (buffer.GetData() == NULL) {
return result;
}
for (unsigned int index = 0; index < count; index++) {
buffer.Zero();
DWORD status = RegEnumValue(FOpenKey, index, buffer.GetData(),
&length, NULL, NULL, NULL, NULL);
while (status == ERROR_MORE_DATA) {
length = length * 2;
if (!buffer.Resize(length)) {
return result;
}
status = RegEnumValue(FOpenKey, index, buffer.GetData(),
&length, NULL, NULL, NULL, NULL);
}
if (status == ERROR_SUCCESS) {
TString value = buffer.GetData();
result.push_back(value);
}
}
}
return result;
}
TString ReadString(TString Name) {
TString result;
DWORD length;
DWORD dwRet;
DynamicBuffer<wchar_t> buffer(0);
length = 0;
dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL, NULL,
&length);
if (dwRet == ERROR_MORE_DATA || dwRet == 0) {
if (!buffer.Resize(length + 1)) {
return result;
}
dwRet = RegQueryValueEx(FOpenKey, Name.data(), NULL, NULL,
(LPBYTE) buffer.GetData(), &length);
result = buffer.GetData();
}
return result;
}
};
WindowsPlatform::WindowsPlatform(void) : Platform() {
FMainThread = ::GetCurrentThreadId();
}
WindowsPlatform::~WindowsPlatform(void) {
}
TString WindowsPlatform::GetPackageAppDirectory() {
return FilePath::IncludeTrailingSeparator(
GetPackageRootDirectory()) + _T("app");
}
TString WindowsPlatform::GetPackageLauncherDirectory() {
return GetPackageRootDirectory();
}
TString WindowsPlatform::GetPackageRuntimeBinDirectory() {
return FilePath::IncludeTrailingSeparator(GetPackageRootDirectory()) + _T("runtime\\bin");
}
TCHAR* WindowsPlatform::ConvertStringToFileSystemString(TCHAR* Source,
bool &release) {
// Not Implemented.
return NULL;
}
TCHAR* WindowsPlatform::ConvertFileSystemStringToString(TCHAR* Source,
bool &release) {
// Not Implemented.
return NULL;
}
TString WindowsPlatform::GetPackageRootDirectory() {
TString result;
TString filename = GetModuleFileName();
return FilePath::ExtractFilePath(filename);
}
TString WindowsPlatform::GetAppDataDirectory() {
TString result;
TCHAR path[MAX_PATH];
if (SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path) == S_OK) {
result = path;
}
return result;
}
TString WindowsPlatform::GetAppName() {
TString result = GetModuleFileName();
result = FilePath::ExtractFileName(result);
result = FilePath::ChangeFileExt(result, _T(""));
return result;
}
void WindowsPlatform::ShowMessage(TString title, TString description) {
MessageBox(NULL, description.data(),
!title.empty() ? title.data() : description.data(),
MB_ICONERROR | MB_OK);
}
void WindowsPlatform::ShowMessage(TString description) {
TString appname = GetModuleFileName();
appname = FilePath::ExtractFileName(appname);
MessageBox(NULL, description.data(), appname.data(), MB_ICONERROR | MB_OK);
}
MessageResponse WindowsPlatform::ShowResponseMessage(TString title,
TString description) {
MessageResponse result = mrCancel;
if (::MessageBox(NULL, description.data(), title.data(), MB_OKCANCEL) ==
IDOK) {
result = mrOK;
}
return result;
}
TString WindowsPlatform::GetBundledJavaLibraryFileName(TString RuntimePath) {
TString result = FilePath::IncludeTrailingSeparator(RuntimePath) +
_T("jre\\bin\\jli.dll");
if (FilePath::FileExists(result) == false) {
result = FilePath::IncludeTrailingSeparator(RuntimePath) +
_T("bin\\jli.dll");
}
return result;
}
ISectionalPropertyContainer* WindowsPlatform::GetConfigFile(TString FileName) {
IniFile *result = new IniFile();
if (result == NULL) {
return NULL;
}
result->LoadFromFile(FileName);
return result;
}
TString WindowsPlatform::GetModuleFileName() {
TString result;
DynamicBuffer<wchar_t> buffer(MAX_PATH);
if (buffer.GetData() == NULL) {
return result;
}
::GetModuleFileName(NULL, buffer.GetData(),
static_cast<DWORD> (buffer.GetSize()));
while (ERROR_INSUFFICIENT_BUFFER == GetLastError()) {
if (!buffer.Resize(buffer.GetSize() * 2)) {
return result;
}
::GetModuleFileName(NULL, buffer.GetData(),
static_cast<DWORD> (buffer.GetSize()));
}
result = buffer.GetData();
return result;
}
Module WindowsPlatform::LoadLibrary(TString FileName) {
return ::LoadLibrary(FileName.data());
}
void WindowsPlatform::FreeLibrary(Module AModule) {
::FreeLibrary((HMODULE) AModule);
}
Procedure WindowsPlatform::GetProcAddress(Module AModule,
std::string MethodName) {
return ::GetProcAddress((HMODULE) AModule, MethodName.c_str());
}
bool WindowsPlatform::IsMainThread() {
bool result = (FMainThread == ::GetCurrentThreadId());
return result;
}
TString WindowsPlatform::GetTempDirectory() {
TString result;
PWSTR userDir = 0;
if (SUCCEEDED(SHGetKnownFolderPath(
FOLDERID_Profile,
0,
NULL,
&userDir))) {
result = userDir;
result += WINDOWS_JPACKAGE_TMP_DIR;
CoTaskMemFree(userDir);
}
return result;
}
static BOOL CALLBACK enumWindows(HWND winHandle, LPARAM lParam) {
DWORD pid = (DWORD) lParam, wPid = 0;
GetWindowThreadProcessId(winHandle, &wPid);
if (pid == wPid) {
SetForegroundWindow(winHandle);
return FALSE;
}
return TRUE;
}
TPlatformNumber WindowsPlatform::GetMemorySize() {
SYSTEM_INFO si;
GetSystemInfo(&si);
size_t result = (size_t) si.lpMaximumApplicationAddress;
result = result / 1048576; // Convert from bytes to megabytes.
return result;
}
std::vector<TString> FilterList(std::vector<TString> &Items,
std::wregex Pattern) {
std::vector<TString> result;
for (std::vector<TString>::iterator it = Items.begin();
it != Items.end(); ++it) {
TString item = *it;
std::wsmatch match;
if (std::regex_search(item, match, Pattern)) {
result.push_back(item);
}
}
return result;
}
Process* WindowsPlatform::CreateProcess() {
return new WindowsProcess();
}
void WindowsPlatform::InitStreamLocale(wios *stream) {
const std::locale empty_locale = std::locale::empty();
const std::locale utf8_locale =
std::locale(empty_locale, new std::codecvt_utf8<wchar_t>());
stream->imbue(utf8_locale);
}
void WindowsPlatform::addPlatformDependencies(JavaLibrary *pJavaLibrary) {
if (pJavaLibrary == NULL) {
return;
}
if (FilePath::FileExists(_T("msvcr100.dll")) == true) {
pJavaLibrary->AddDependency(_T("msvcr100.dll"));
}
TString runtimeBin = GetPackageRuntimeBinDirectory();
SetDllDirectory(runtimeBin.c_str());
}
void Platform::CopyString(char *Destination,
size_t NumberOfElements, const char *Source) {
strcpy_s(Destination, NumberOfElements, Source);
if (NumberOfElements > 0) {
Destination[NumberOfElements - 1] = '\0';
}
}
void Platform::CopyString(wchar_t *Destination,
size_t NumberOfElements, const wchar_t *Source) {
wcscpy_s(Destination, NumberOfElements, Source);
if (NumberOfElements > 0) {
Destination[NumberOfElements - 1] = '\0';
}
}
// Owner must free the return value.
MultibyteString Platform::WideStringToMultibyteString(
const wchar_t* value) {
MultibyteString result;
size_t count = 0;
if (value == NULL) {
return result;
}
count = WideCharToMultiByte(CP_UTF8, 0, value, -1, NULL, 0, NULL, NULL);
if (count > 0) {
result.data = new char[count + 1];
result.length = WideCharToMultiByte(CP_UTF8, 0, value, -1,
result.data, (int)count, NULL, NULL);
}
return result;
}
// Owner must free the return value.
WideString Platform::MultibyteStringToWideString(const char* value) {
WideString result;
size_t count = 0;
if (value == NULL) {
return result;
}
count = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS,
value, -1, NULL, 0);
if (count > 0) {
result.data = new wchar_t[count];
result.length = MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS,
value, -1, result.data, (int)count);
if (result.length == 0) {
delete[] result.data;
result.data = NULL;
}
}
return result;
}
FileHandle::FileHandle(std::wstring FileName) {
FHandle = ::CreateFile(FileName.data(), GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
}
FileHandle::~FileHandle() {
if (IsValid() == true) {
::CloseHandle(FHandle);
}
}
bool FileHandle::IsValid() {
return FHandle != INVALID_HANDLE_VALUE;
}
HANDLE FileHandle::GetHandle() {
return FHandle;
}
FileMappingHandle::FileMappingHandle(HANDLE FileHandle) {
FHandle = ::CreateFileMapping(FileHandle, NULL, PAGE_READONLY, 0, 0, NULL);
}
bool FileMappingHandle::IsValid() {
return FHandle != NULL;
}
FileMappingHandle::~FileMappingHandle() {
if (IsValid() == true) {
::CloseHandle(FHandle);
}
}
HANDLE FileMappingHandle::GetHandle() {
return FHandle;
}
FileData::FileData(HANDLE Handle) {
FBaseAddress = ::MapViewOfFile(Handle, FILE_MAP_READ, 0, 0, 0);
}
FileData::~FileData() {
if (IsValid() == true) {
::UnmapViewOfFile(FBaseAddress);
}
}
bool FileData::IsValid() {
return FBaseAddress != NULL;
}
LPVOID FileData::GetBaseAddress() {
return FBaseAddress;
}
WindowsLibrary::WindowsLibrary(std::wstring FileName) {
FFileName = FileName;
}
std::vector<TString> WindowsLibrary::GetImports() {
std::vector<TString> result;
FileHandle library(FFileName);
if (library.IsValid() == true) {
FileMappingHandle mapping(library.GetHandle());
if (mapping.IsValid() == true) {
FileData fileData(mapping.GetHandle());
if (fileData.IsValid() == true) {
PIMAGE_DOS_HEADER dosHeader =
(PIMAGE_DOS_HEADER) fileData.GetBaseAddress();
PIMAGE_FILE_HEADER pImgFileHdr =
(PIMAGE_FILE_HEADER) fileData.GetBaseAddress();
if (dosHeader->e_magic == IMAGE_DOS_SIGNATURE) {
result = DumpPEFile(dosHeader);
}
}
}
}
return result;
}
// Given an RVA, look up the section header that encloses it and return a
// pointer to its IMAGE_SECTION_HEADER
PIMAGE_SECTION_HEADER WindowsLibrary::GetEnclosingSectionHeader(DWORD rva,
PIMAGE_NT_HEADERS pNTHeader) {
PIMAGE_SECTION_HEADER result = 0;
PIMAGE_SECTION_HEADER section = IMAGE_FIRST_SECTION(pNTHeader);
for (unsigned index = 0; index < pNTHeader->FileHeader.NumberOfSections;
index++, section++) {
// Is the RVA is within this section?
if ((rva >= section->VirtualAddress) &&
(rva < (section->VirtualAddress + section->Misc.VirtualSize))) {
result = section;
}
}
return result;
}
LPVOID WindowsLibrary::GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader,
DWORD imageBase) {
LPVOID result = 0;
PIMAGE_SECTION_HEADER pSectionHdr = GetEnclosingSectionHeader(rva,
pNTHeader);
if (pSectionHdr != NULL) {
INT delta = (INT) (
pSectionHdr->VirtualAddress - pSectionHdr->PointerToRawData);
DWORD_PTR dwp = (DWORD_PTR) (imageBase + rva - delta);
result = reinterpret_cast<LPVOID> (dwp); // VS2017 - FIXME
}
return result;
}
std::vector<TString> WindowsLibrary::GetImportsSection(DWORD base,
PIMAGE_NT_HEADERS pNTHeader) {
std::vector<TString> result;
// Look up where the imports section is located. Normally in
// the .idata section,
// but not necessarily so. Therefore, grab the RVA from the data dir.
DWORD importsStartRVA = pNTHeader->OptionalHeader.DataDirectory[
IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
if (importsStartRVA != NULL) {
// Get the IMAGE_SECTION_HEADER that contains the imports. This is
// usually the .idata section, but doesn't have to be.
PIMAGE_SECTION_HEADER pSection =
GetEnclosingSectionHeader(importsStartRVA, pNTHeader);
if (pSection != NULL) {
PIMAGE_IMPORT_DESCRIPTOR importDesc =
(PIMAGE_IMPORT_DESCRIPTOR) GetPtrFromRVA(
importsStartRVA, pNTHeader, base);
if (importDesc != NULL) {
while (true) {
// See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR
if ((importDesc->TimeDateStamp == 0) &&
(importDesc->Name == 0)) {
break;
}
std::string filename = (char*) GetPtrFromRVA(
importDesc->Name, pNTHeader, base);
result.push_back(PlatformString(filename));
importDesc++; // advance to next IMAGE_IMPORT_DESCRIPTOR
}
}
}
}
return result;
}
std::vector<TString> WindowsLibrary::DumpPEFile(PIMAGE_DOS_HEADER dosHeader) {
std::vector<TString> result;
// all of this is VS2017 - FIXME
DWORD_PTR dwDosHeaders = reinterpret_cast<DWORD_PTR> (dosHeader);
DWORD_PTR dwPIHeaders = dwDosHeaders + (DWORD) (dosHeader->e_lfanew);
PIMAGE_NT_HEADERS pNTHeader =
reinterpret_cast<PIMAGE_NT_HEADERS> (dwPIHeaders);
// Verify that the e_lfanew field gave us a reasonable
// pointer and the PE signature.
// TODO: To really fix JDK-8131321 this condition needs to be changed.
// There is a matching change
// in JavaVirtualMachine.cpp that also needs to be changed.
if (pNTHeader->Signature == IMAGE_NT_SIGNATURE) {
DWORD base = (DWORD) (dwDosHeaders);
result = GetImportsSection(base, pNTHeader);
}
return result;
}
#include <TlHelp32.h>
WindowsJob::WindowsJob() {
FHandle = NULL;
}
WindowsJob::~WindowsJob() {
if (FHandle != NULL) {
CloseHandle(FHandle);
}
}
HANDLE WindowsJob::GetHandle() {
if (FHandle == NULL) {
FHandle = CreateJobObject(NULL, NULL); // GLOBAL
if (FHandle == NULL) {
::MessageBox(0, _T("Could not create job object"),
_T("TEST"), MB_OK);
} else {
JOBOBJECT_EXTENDED_LIMIT_INFORMATION jeli = {0};
// Configure all child processes associated with
// the job to terminate when the
jeli.BasicLimitInformation.LimitFlags =
JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
if (0 == SetInformationJobObject(FHandle,
JobObjectExtendedLimitInformation, &jeli, sizeof (jeli))) {
::MessageBox(0, _T("Could not SetInformationJobObject"),
_T("TEST"), MB_OK);
}
}
}
return FHandle;
}
// Initialize static member of WindowsProcess
WindowsJob WindowsProcess::FJob;
WindowsProcess::WindowsProcess() : Process() {
FRunning = false;
}
WindowsProcess::~WindowsProcess() {
Terminate();
}
void WindowsProcess::Cleanup() {
CloseHandle(FProcessInfo.hProcess);
CloseHandle(FProcessInfo.hThread);
}
bool WindowsProcess::IsRunning() {
bool result = false;
HANDLE handle = ::CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
if (handle == INVALID_HANDLE_VALUE) {
return false;
}
PROCESSENTRY32 process = {0};
process.dwSize = sizeof (process);
if (::Process32First(handle, &process)) {
do {
if (process.th32ProcessID == FProcessInfo.dwProcessId) {
result = true;
break;
}
} while (::Process32Next(handle, &process));
}
CloseHandle(handle);
return result;
}
bool WindowsProcess::Terminate() {
bool result = false;
if (IsRunning() == true && FRunning == true) {
FRunning = false;
}
return result;
}
bool WindowsProcess::Execute(const TString Application,
const std::vector<TString> Arguments, bool AWait) {
bool result = false;
if (FRunning == false) {
FRunning = true;
STARTUPINFO startupInfo;
ZeroMemory(&startupInfo, sizeof (startupInfo));
startupInfo.cb = sizeof (startupInfo);
ZeroMemory(&FProcessInfo, sizeof (FProcessInfo));
TString command = Application;
for (std::vector<TString>::const_iterator iterator = Arguments.begin();
iterator != Arguments.end(); iterator++) {
command += TString(_T(" ")) + *iterator;
}
if (::CreateProcess(Application.data(), (wchar_t*)command.data(), NULL,
NULL, FALSE, 0, NULL, NULL, &startupInfo, &FProcessInfo)
== FALSE) {
TString message = PlatformString::Format(
_T("Error: Unable to create process %s"),
Application.data());
throw Exception(message);
} else {
if (FJob.GetHandle() != NULL) {
if (::AssignProcessToJobObject(FJob.GetHandle(),
FProcessInfo.hProcess) == 0) {
// Failed to assign process to job. It doesn't prevent
// anything from continuing so continue.
}
}
// Wait until child process exits.
if (AWait == true) {
Wait();
// Close process and thread handles.
Cleanup();
}
}
}
return result;
}
bool WindowsProcess::Wait() {
bool result = false;
WaitForSingleObject(FProcessInfo.hProcess, INFINITE);
return result;
}
TProcessID WindowsProcess::GetProcessID() {
return FProcessInfo.dwProcessId;
}
bool WindowsProcess::ReadOutput() {
bool result = false;
// TODO implement
return result;
}
void WindowsProcess::SetInput(TString Value) {
// TODO implement
}
std::list<TString> WindowsProcess::GetOutput() {
ReadOutput();
return Process::GetOutput();
}

View File

@ -1,171 +0,0 @@
/*
* Copyright (c) 2014, 2019, 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.
*/
#ifndef WINDOWSPLATFORM_H
#define WINDOWSPLATFORM_H
#include <Windows.h>
#include "Platform.h"
class WindowsPlatform : virtual public Platform {
private:
DWORD FMainThread;
public:
WindowsPlatform(void);
virtual ~WindowsPlatform(void);
virtual TCHAR* ConvertStringToFileSystemString(TCHAR* Source,
bool &release);
virtual TCHAR* ConvertFileSystemStringToString(TCHAR* Source,
bool &release);
virtual void ShowMessage(TString title, TString description);
virtual void ShowMessage(TString description);
virtual MessageResponse ShowResponseMessage(TString title,
TString description);
virtual TString GetPackageRootDirectory();
virtual TString GetAppDataDirectory();
virtual TString GetAppName();
virtual TString GetBundledJavaLibraryFileName(TString RuntimePath);
TString GetPackageAppDirectory();
TString GetPackageLauncherDirectory();
TString GetPackageRuntimeBinDirectory();
virtual ISectionalPropertyContainer* GetConfigFile(TString FileName);
virtual TString GetModuleFileName();
virtual Module LoadLibrary(TString FileName);
virtual void FreeLibrary(Module AModule);
virtual Procedure GetProcAddress(Module AModule, std::string MethodName);
virtual Process* CreateProcess();
virtual bool IsMainThread();
virtual TPlatformNumber GetMemorySize();
virtual TString GetTempDirectory();
void InitStreamLocale(wios *stream);
void addPlatformDependencies(JavaLibrary *pJavaLibrary);
};
class FileHandle {
private:
HANDLE FHandle;
public:
FileHandle(std::wstring FileName);
~FileHandle();
bool IsValid();
HANDLE GetHandle();
};
class FileMappingHandle {
private:
HANDLE FHandle;
public:
FileMappingHandle(HANDLE FileHandle);
~FileMappingHandle();
bool IsValid();
HANDLE GetHandle();
};
class FileData {
private:
LPVOID FBaseAddress;
public:
FileData(HANDLE Handle);
~FileData();
bool IsValid();
LPVOID GetBaseAddress();
};
class WindowsLibrary {
private:
TString FFileName;
// Given an RVA, look up the section header that encloses it and return a
// pointer to its IMAGE_SECTION_HEADER
static PIMAGE_SECTION_HEADER GetEnclosingSectionHeader(DWORD rva,
PIMAGE_NT_HEADERS pNTHeader);
static LPVOID GetPtrFromRVA(DWORD rva, PIMAGE_NT_HEADERS pNTHeader,
DWORD imageBase);
static std::vector<TString> GetImportsSection(DWORD base,
PIMAGE_NT_HEADERS pNTHeader);
static std::vector<TString> DumpPEFile(PIMAGE_DOS_HEADER dosHeader);
public:
WindowsLibrary(const TString FileName);
std::vector<TString> GetImports();
};
class WindowsJob {
private:
HANDLE FHandle;
public:
WindowsJob();
~WindowsJob();
HANDLE GetHandle();
};
class WindowsProcess : public Process {
private:
bool FRunning;
PROCESS_INFORMATION FProcessInfo;
static WindowsJob FJob;
void Cleanup();
bool ReadOutput();
public:
WindowsProcess();
virtual ~WindowsProcess();
virtual bool IsRunning();
virtual bool Terminate();
virtual bool Execute(const TString Application,
const std::vector<TString> Arguments, bool AWait = false);
virtual bool Wait();
virtual TProcessID GetProcessID();
virtual void SetInput(TString Value);
virtual std::list<TString> GetOutput();
};
#endif // WINDOWSPLATFORM_H

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -30,6 +30,8 @@
#include "Utils.h" #include "Utils.h"
#pragma comment(lib, "advapi32")
// Max value name size per MSDN plus NULL // Max value name size per MSDN plus NULL
#define VALUE_NAME_SIZE 16384 #define VALUE_NAME_SIZE 16384

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2011, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -105,11 +105,6 @@ extern "C" {
return 1; return 1;
} }
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
LPVOID lpvReserved) {
return TRUE;
}
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -1,8 +1,34 @@
/*
* Copyright (c) 2019, 2020, 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 <algorithm> #include <algorithm>
#include <windows.h> #include <windows.h>
#include "SysInfo.h" #include "SysInfo.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "WinFileUtils.h"
#include "Executor.h" #include "Executor.h"
#include "Resources.h" #include "Resources.h"
#include "WinErrorHandling.h" #include "WinErrorHandling.h"

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -25,6 +25,7 @@
#include "Resources.h" #include "Resources.h"
#include "FileUtils.h" #include "FileUtils.h"
#include "WinFileUtils.h"
#include "WinErrorHandling.h" #include "WinErrorHandling.h"
#include <fstream> #include <fstream>

View File

@ -1,10 +1,12 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * 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 * under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. * 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 * This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
@ -20,6 +22,7 @@
* or visit www.oracle.com if you need additional information or have any * or visit www.oracle.com if you need additional information or have any
* questions. * questions.
*/ */
package jdk.jpackage.test; package jdk.jpackage.test;
import java.io.FileOutputStream; import java.io.FileOutputStream;
@ -733,10 +736,10 @@ public final class JPackageCommand extends CommandArguments<JPackageCommand> {
return args.stream().map(v -> { return args.stream().map(v -> {
String str = v; String str = v;
// Escape quotes.
str = str.replace("\"", "\\\"");
// Escape backslashes. // Escape backslashes.
str = str.replace("\\", "\\\\"); str = str.replace("\\", "\\\\");
// Escape quotes.
str = str.replace("\"", "\\\"");
// If value contains whitespace characters, put the value in quotes // If value contains whitespace characters, put the value in quotes
if (whitespaceRegexp.matcher(str).find()) { if (whitespaceRegexp.matcher(str).find()) {
str = "\"" + str + "\""; str = "\"" + str + "\"";

View File

@ -1,5 +1,5 @@
/* /*
* Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
@ -82,7 +82,6 @@ public class ApplicationLayoutTest {
assertTrue(Files.isDirectory(layout.appModsDirectory())); assertTrue(Files.isDirectory(layout.appModsDirectory()));
assertTrue(Files.isRegularFile(layout.launchersDirectory().resolve("Foo"))); assertTrue(Files.isRegularFile(layout.launchersDirectory().resolve("Foo")));
assertTrue(Files.isRegularFile(layout.destktopIntegrationDirectory().resolve("Foo.png"))); assertTrue(Files.isRegularFile(layout.destktopIntegrationDirectory().resolve("Foo.png")));
assertTrue(Files.isRegularFile(layout.dllDirectory().resolve("libapplauncher.so")));
assertTrue(Files.isRegularFile(layout.runtimeDirectory().resolve("bin/java"))); assertTrue(Files.isRegularFile(layout.runtimeDirectory().resolve("bin/java")));
} }

View File

@ -0,0 +1,57 @@
/*
* Copyright (c) 2019, 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.
*
* 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.
*/
package jdk.jpackage.tests;
import java.nio.file.Path;
import jdk.jpackage.test.Annotations.Test;
import jdk.jpackage.test.Annotations.Parameter;
import jdk.jpackage.test.HelloApp;
import jdk.jpackage.test.JavaAppDesc;
import jdk.jpackage.test.JPackageCommand;
/*
* @test
* @summary jpackage application packed in multiple jars
* @library ../../../../helpers
* @build jdk.jpackage.test.*
* @modules jdk.incubator.jpackage/jdk.incubator.jpackage.internal
* @compile MultipleJarAppTest.java
* @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main
* --jpt-run=jdk.jpackage.tests.MultipleJarAppTest
*/
public final class MultipleJarAppTest {
@Test
@Parameter("B")
@Parameter("C")
public void test(String mainClass) {
JPackageCommand cmd = JPackageCommand.helloAppImage("a.jar:A");
HelloApp.createBundle(JavaAppDesc.parse("b.jar:B"), cmd.inputDir());
HelloApp.createBundle(JavaAppDesc.parse("c.jar:C"), cmd.inputDir());
cmd.setArgumentValue("--main-class", mainClass);
cmd.executeAndAssertHelloAppImageCreated();
}
}