This commit is contained in:
Prasanta Sadhukhan 2020-04-24 16:12:53 +05:30
commit 059329b346
184 changed files with 7874 additions and 11145 deletions
make
src
hotspot
java.base/share/classes/sun/security/ssl
jdk.compiler/share/classes/com/sun/tools/javac/parser
jdk.hotspot.agent/share/classes/sun/jvm/hotspot/oops
jdk.incubator.jpackage

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2018, 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.
#
# This code is free software; you can redistribute it and/or modify it
@ -79,7 +79,7 @@ AC_DEFUN([LIB_CHECK_POTENTIAL_FREETYPE],
AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
[
AC_ARG_WITH(freetype, [AS_HELP_STRING([--with-freetype],
[specify whether to use 'system' or 'bundled' freetype. Other values are errors.
[specify whether to use 'system' or 'bundled' freetype.
The selected option applies to both build time and run time.
The default behaviour can be platform dependent.
If using 'system' and either the include files or libraries cannot be
@ -90,76 +90,90 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
AC_ARG_WITH(freetype-lib, [AS_HELP_STRING([--with-freetype-lib],
[specify directory for the freetype library])])
# This setup is to verify access to system installed freetype header and libraries.
# On Windows and MacOS this does not apply and using these options will report an error.
# On other platforms (Linux, Solaris), they will default to using
# the system libraries. If they are found automatically, nothing need be done.
# If they are not found, the configure "--with-freetype-*" options may be used to fix that.
# If the preference is to bundle on these platforms then use --with-freetype=bundled
# This setup is to verify access to system installed freetype header and
# libraries. On Windows and MacOS this does not apply and using these options
# will report an error. On other platforms (Linux, Solaris), they will
# default to using the system libraries. If they are found automatically,
# nothing need be done. If they are not found, the configure
# "--with-freetype-*" options may be used to fix that. If the preference is
# to bundle on these platforms then use --with-freetype=bundled.
FREETYPE_BASE_NAME=freetype
FREETYPE_CFLAGS=
FREETYPE_LIBS=
if (test "x$with_freetype_include" = "x" && test "x$with_freetype_lib" != "x") || \
(test "x$with_freetype_include" != "x" && test "x$with_freetype_lib" = "x"); then
AC_MSG_ERROR(['must specify both or neither of --with-freetype-include and --with-freetype-lib])
if (test "x$with_freetype_include" = "x" && test "x$with_freetype_lib" != "x") || \
(test "x$with_freetype_include" != "x" && test "x$with_freetype_lib" = "x"); then
AC_MSG_ERROR([Must specify both or neither of --with-freetype-include and --with-freetype-lib])
fi
FREETYPE_TO_USE=bundled
if (test "x$OPENJDK_TARGET_OS" != "xwindows" && test "x$OPENJDK_TARGET_OS" != "xmacosx" \
&& test "x$OPENJDK_TARGET_OS" != "xaix"); then
if test "x$OPENJDK_TARGET_OS" != "xwindows" && \
test "x$OPENJDK_TARGET_OS" != "xmacosx" && \
test "x$OPENJDK_TARGET_OS" != "xaix"; then
FREETYPE_TO_USE=system
fi
if (test "x$with_freetype" != "x"); then
if (test "x$with_freetype" = "xsystem"); then
if test "x$with_freetype" != "x" ; then
if test "x$with_freetype" = "xsystem" ; then
FREETYPE_TO_USE=system
elif (test "x$with_freetype" = "xbundled"); then
elif test "x$with_freetype" = "xbundled" ; then
FREETYPE_TO_USE=bundled
if (test "x$with_freetype_include" != "x" || test "x$with_freetype_lib" != "x"); then
if test "x$with_freetype_include" != "x" || \
test "x$with_freetype_lib" != "x" ; then
AC_MSG_ERROR(['bundled' cannot be specified with --with-freetype-include and --with-freetype-lib])
fi
else
AC_MSG_ERROR(['valid values for --with-freetype are 'system' and 'bundled'])
AC_MSG_ERROR([Valid values for --with-freetype are 'system' and 'bundled'])
fi
fi
if (test "x$with_freetype_include" != "x" && test "x$with_freetype_lib" != "x"); then
FREETYPE_TO_USE=system
if test "x$with_freetype_include" != "x" && \
test "x$with_freetype_lib" != "x" ; then
FREETYPE_TO_USE=system
fi
if (test "x$FREETYPE_TO_USE" = "xsystem") && \
(test "x$OPENJDK_TARGET_OS" = "xwindows" || test "x$OPENJDK_TARGET_OS" = "xmacosx"); then
AC_MSG_ERROR([Only bundled freetype can be specified on Mac and Windows])
if test "x$FREETYPE_TO_USE" = "xsystem" && \
(test "x$OPENJDK_TARGET_OS" = "xwindows" || \
test "x$OPENJDK_TARGET_OS" = "xmacosx"); then
AC_MSG_ERROR([Only bundled freetype can be specified on Mac and Windows])
fi
if (test "x$with_freetype_include" != "x"); then
if test "x$with_freetype_include" != "x" ; then
POTENTIAL_FREETYPE_INCLUDE_PATH="$with_freetype_include"
fi
if (test "x$with_freetype_lib" != "x"); then
if test "x$with_freetype_lib" != "x" ; then
POTENTIAL_FREETYPE_LIB_PATH="$with_freetype_lib"
fi
if (test "x$FREETYPE_TO_USE" = "xsystem"); then
if (test "x$POTENTIAL_FREETYPE_INCLUDE_PATH" != "x" && test "x$POTENTIAL_FREETYPE_LIB_PATH" != "x"); then
if test "x$FREETYPE_TO_USE" = "xsystem" ; then
if test "x$POTENTIAL_FREETYPE_INCLUDE_PATH" != "x" && \
test "x$POTENTIAL_FREETYPE_LIB_PATH" != "x" ; then
# Okay, we got it. Check that it works.
LIB_CHECK_POTENTIAL_FREETYPE($POTENTIAL_FREETYPE_INCLUDE_PATH, $POTENTIAL_FREETYPE_LIB_PATH, [--with-freetype])
if (test "x$FOUND_FREETYPE" != "xyes"); then
LIB_CHECK_POTENTIAL_FREETYPE($POTENTIAL_FREETYPE_INCLUDE_PATH,
$POTENTIAL_FREETYPE_LIB_PATH, [--with-freetype])
if test "x$FOUND_FREETYPE" != "xyes" ; then
AC_MSG_ERROR([Can not find or use freetype at location given by --with-freetype-lib|include])
fi
else
# User did not specify a location, but asked for system freetype. Try to locate it.
# User did not specify a location, but asked for system freetype.
# Try to locate it.
# If we have a sysroot, assume that's where we are supposed to look and skip pkg-config.
if (test "x$SYSROOT" = "x"); then
if (test "x$FOUND_FREETYPE" != "xyes"); then
# Check modules using pkg-config, but only if we have it (ugly output results otherwise)
if (test "x$PKG_CONFIG" != "x"); then
# If we have a sysroot, assume that's where we are supposed to look and
# skip pkg-config.
if test "x$SYSROOT" = "x" ; then
if test "x$FOUND_FREETYPE" != "xyes" ; then
# Check modules using pkg-config, but only if we have it (ugly output
# results otherwise)
if test "x$PKG_CONFIG" != "x" ; then
PKG_CHECK_MODULES(FREETYPE, freetype2, [FOUND_FREETYPE=yes], [FOUND_FREETYPE=no])
if (test "x$FOUND_FREETYPE" = "xyes"); then
# On solaris, pkg_check adds -lz to freetype libs, which isn't necessary for us.
if test "x$FOUND_FREETYPE" = "xyes" ; then
# On solaris, pkg_check adds -lz to freetype libs, which isn't
# necessary for us.
FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's/-lz//g'`
# 64-bit libs for Solaris x86 are installed in the amd64 subdirectory, change lib to lib/amd64
if (test "x$OPENJDK_TARGET_OS" = "xsolaris" && test "x$OPENJDK_TARGET_CPU" = "xx86_64"); then
# 64-bit libs for Solaris x86 are installed in the amd64
# subdirectory, change lib to lib/amd64
if test "x$OPENJDK_TARGET_OS" = "xsolaris" && \
test "x$OPENJDK_TARGET_CPU" = "xx86_64" ; then
FREETYPE_LIBS=`$ECHO $FREETYPE_LIBS | $SED 's?/lib?/lib/amd64?g'`
fi
AC_MSG_CHECKING([for freetype])
@ -169,59 +183,65 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE],
fi
fi
if (test "x$FOUND_FREETYPE" != "xyes"); then
if test "x$FOUND_FREETYPE" != "xyes" ; then
# Check in well-known locations
FREETYPE_BASE_DIR="$SYSROOT/usr"
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
if (test "x$FOUND_FREETYPE" != "xyes"); then
FREETYPE_BASE_DIR="$SYSROOT/usr/X11"
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
fi
if (test "x$FOUND_FREETYPE" != "xyes"); then
FREETYPE_BASE_DIR="$SYSROOT/usr/local"
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib], [well-known location])
fi
if (test "x$FOUND_FREETYPE" != "xyes"); then
FREETYPE_BASE_DIR="$SYSROOT/usr"
if (test "x$OPENJDK_TARGET_CPU_BITS" = "x64"); then
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib/$OPENJDK_TARGET_CPU-linux-gnu], [well-known location])
if (test "x$FOUND_FREETYPE" != "xyes"); then
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib64], [well-known location])
fi
else
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib/i386-linux-gnu], [well-known location])
if (test "x$FOUND_FREETYPE" != "xyes"); then
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include], [$FREETYPE_BASE_DIR/lib32], [well-known location])
fi
if test "x$OPENJDK_TARGET_CPU_BITS" = "x64" ; then
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include],
[$FREETYPE_BASE_DIR/lib/$OPENJDK_TARGET_CPU-linux-gnu], [well-known location])
if test "x$FOUND_FREETYPE" != "xyes" ; then
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include],
[$FREETYPE_BASE_DIR/lib64], [well-known location])
fi
else
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include],
[$FREETYPE_BASE_DIR/lib/i386-linux-gnu], [well-known location])
if test "x$FOUND_FREETYPE" != "xyes" ; then
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include],
[$FREETYPE_BASE_DIR/lib32], [well-known location])
fi
fi
if test "x$FOUND_FREETYPE" != "xyes" ; then
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include],
[$FREETYPE_BASE_DIR/lib], [well-known location])
fi
if test "x$FOUND_FREETYPE" != "xyes" ; then
FREETYPE_BASE_DIR="$SYSROOT/usr/X11"
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include],
[$FREETYPE_BASE_DIR/lib], [well-known location])
fi
if test "x$FOUND_FREETYPE" != "xyes" ; then
FREETYPE_BASE_DIR="$SYSROOT/usr/local"
LIB_CHECK_POTENTIAL_FREETYPE([$FREETYPE_BASE_DIR/include],
[$FREETYPE_BASE_DIR/lib], [well-known location])
fi
fi # end check in well-known locations
if (test "x$FOUND_FREETYPE" != "xyes"); then
if test "x$FOUND_FREETYPE" != "xyes" ; then
HELP_MSG_MISSING_DEPENDENCY([freetype])
AC_MSG_ERROR([Could not find freetype! $HELP_MSG ])
fi
fi # end user specified settings
# Set FREETYPE_CFLAGS, _LIBS and _LIB_PATH from include and lib dir.
if (test "x$FREETYPE_CFLAGS" = "x"); then
if (test -d $FREETYPE_INCLUDE_PATH/freetype2/freetype); then
if test "x$FREETYPE_CFLAGS" = "x" ; then
if test -d $FREETYPE_INCLUDE_PATH/freetype2/freetype ; then
FREETYPE_CFLAGS="-I$FREETYPE_INCLUDE_PATH/freetype2 -I$FREETYPE_INCLUDE_PATH"
else
FREETYPE_CFLAGS="-I$FREETYPE_INCLUDE_PATH"
fi
fi
if (test "x$FREETYPE_LIBS" = "x"); then
if test "x$FREETYPE_LIBS" = "x" ; then
FREETYPE_LIBS="-L$FREETYPE_LIB_PATH -l$FREETYPE_BASE_NAME"
fi
fi
AC_MSG_RESULT([Using freetype: $FREETYPE_TO_USE])
AC_MSG_RESULT([Using freetype: $FREETYPE_TO_USE])
AC_SUBST(FREETYPE_TO_USE)
AC_SUBST(FREETYPE_CFLAGS)

@ -86,7 +86,7 @@ DISABLED_WARNINGS_gcc := parentheses comment unknown-pragmas address \
delete-non-virtual-dtor char-subscripts array-bounds int-in-bool-context \
ignored-qualifiers missing-field-initializers implicit-fallthrough \
empty-body strict-overflow sequence-point maybe-uninitialized \
misleading-indentation cast-function-type invalid-offsetof
misleading-indentation cast-function-type
ifeq ($(call check-jvm-feature, zero), true)
DISABLED_WARNINGS_gcc += return-type switch clobbered
@ -95,8 +95,7 @@ endif
DISABLED_WARNINGS_clang := tautological-compare \
undefined-var-template sometimes-uninitialized unknown-pragmas \
delete-non-virtual-dtor missing-braces char-subscripts \
ignored-qualifiers missing-field-initializers mismatched-tags \
invalid-offsetof
ignored-qualifiers missing-field-initializers mismatched-tags
DISABLED_WARNINGS_solstudio := labelnotused hidef w_novirtualdescr inlafteruse \
unknownpragma doubunder w_enumnotused w_toomanyenumnotused \

@ -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.
#
# 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 := \
$(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
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHEREXE, \
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, \
SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKEXE), \
CXXFLAGS := $(CXXFLAGS_JDKEXE), \
CFLAGS_windows := -EHsc -DLAUNCHERC -DUNICODE -D_UNICODE, \
CXXFLAGS := $(call JpackageWithStaticCrt, $(CXXFLAGS_JDKEXE)) \
$(addprefix -I, $(JPACKAGE_APPLAUNCHER_SRC)), \
CXXFLAGS_windows := $(JPACKAGE_CXXFLAGS_windows), \
LDFLAGS := $(LDFLAGS_JDKEXE), \
LIBS_macosx := -framework Cocoa, \
LIBS := $(LIBCXX), \
LIBS_linux := -ldl, \
LIBS_windows := user32.lib shell32.lib advapi32.lib, \
))
$(BUILD_JPACKAGE_APPLAUNCHEREXE): $(call FindLib, java.base, java)
TARGETS += $(BUILD_JPACKAGE_APPLAUNCHEREXE)
################################################################################
@ -78,12 +73,11 @@ ifeq ($(call isTargetOs, windows), true)
$(eval $(call SetupJdkLibrary, BUILD_LIB_JPACKAGE, \
NAME := jpackage, \
OPTIMIZATION := LOW, \
CFLAGS := $(CXXFLAGS_JDKLIB), \
CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
EXTRA_SRC := jdk.incubator.jpackage:common, \
CXXFLAGS := $(CXXFLAGS_JDKLIB) $(JPACKAGE_CXXFLAGS_windows), \
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
$(call SET_SHARED_LIBRARY_ORIGIN), \
LIBS := $(LIBCXX), \
LIBS_windows := user32.lib shell32.lib advapi32.lib ole32.lib, \
))
TARGETS += $(BUILD_LIB_JPACKAGE)
@ -92,11 +86,11 @@ ifeq ($(call isTargetOs, windows), true)
# Output library in resources dir, and symbols in the object dir
$(eval $(call SetupJdkLibrary, BUILD_LIB_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, \
OPTIMIZATION := LOW, \
CFLAGS := $(CXXFLAGS_JDKLIB), \
CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE -MT, \
CXXFLAGS := $(call JpackageWithStaticCrt, $(CXXFLAGS_JDKLIB)) \
$(JPACKAGE_CXXFLAGS_windows), \
LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK), \
LIBS := $(LIBCXX), \
LIBS_windows := msi.lib Shlwapi.lib User32.lib, \
@ -104,17 +98,18 @@ ifeq ($(call isTargetOs, windows), true)
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
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_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, \
SRC := $(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/msiwrapper, \
EXTRA_FILES := $(addprefix $(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/libjpackage/, \
FileUtils.cpp Log.cpp WinSysInfo.cpp tstrings.cpp WinErrorHandling.cpp ErrorHandling.cpp), \
CFLAGS := $(CXXFLAGS_JDKEXE) -MT \
$(addprefix -I$(TOPDIR)/src/jdk.incubator.jpackage/$(OPENJDK_TARGET_OS)/native/, msiwrapper libjpackage), \
CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
SRC := $(JPACKAGE_MSIWRAPPER_SRC), \
CXXFLAGS := $(call JpackageWithStaticCrt, $(CXXFLAGS_JDKEXE)) \
$(addprefix -I, $(JPACKAGE_MSIWRAPPER_SRC)) $(JPACKAGE_CXXFLAGS_windows), \
LDFLAGS := $(LDFLAGS_JDKEXE), \
LIBS := $(LIBCXX), \
))
@ -123,18 +118,17 @@ ifeq ($(call isTargetOs, windows), true)
# Build non-console version of launcher
$(eval $(call SetupJdkExecutable, BUILD_JPACKAGE_APPLAUNCHERWEXE, \
NAME := jpackageapplauncherw, \
OUTPUT_DIR := $(JDK_OUTPUTDIR)/modules/$(MODULE)/jdk/incubator/jpackage/internal/resources, \
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \
SRC := $(JPACKAGE_APPLAUNCHER_SRC), \
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
OPTIMIZATION := LOW, \
CFLAGS := $(CXXFLAGS_JDKEXE), \
CFLAGS_windows := -EHsc -DUNICODE -D_UNICODE, \
LDFLAGS := $(LDFLAGS_JDKEXE), \
LIBS := $(LIBCXX), \
LIBS_windows := user32.lib shell32.lib advapi32.lib, \
))
NAME := jpackageapplauncherw, \
OUTPUT_DIR := $(JPACKAGE_OUTPUT_DIR), \
SYMBOLS_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/jpackageapplauncherw, \
SRC := $(BUILD_JPACKAGE_APPLAUNCHEREXE_SRC), \
TOOLCHAIN := $(BUILD_JPACKAGE_APPLAUNCHEREXE_TOOLCHAIN), \
OPTIMIZATION := $(BUILD_JPACKAGE_APPLAUNCHEREXE_OPTIMIZATION), \
CXXFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS), \
CXXFLAGS_windows := $(BUILD_JPACKAGE_APPLAUNCHEREXE_CXXFLAGS_windows) -DJP_LAUNCHERW, \
LDFLAGS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LDFLAGS), \
LIBS := $(BUILD_JPACKAGE_APPLAUNCHEREXE_LIBS), \
))
TARGETS += $(BUILD_JPACKAGE_APPLAUNCHERWEXE)

@ -16619,6 +16619,35 @@ instruct vsub2D(vecX dst, vecX src1, vecX src2)
// --------------------------------- MUL --------------------------------------
instruct vmul8B(vecD dst, vecD src1, vecD src2)
%{
predicate(n->as_Vector()->length() == 4 ||
n->as_Vector()->length() == 8);
match(Set dst (MulVB src1 src2));
ins_cost(INSN_COST);
format %{ "mulv $dst,$src1,$src2\t# vector (8B)" %}
ins_encode %{
__ mulv(as_FloatRegister($dst$$reg), __ T8B,
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg));
%}
ins_pipe(vmul64);
%}
instruct vmul16B(vecX dst, vecX src1, vecX src2)
%{
predicate(n->as_Vector()->length() == 16);
match(Set dst (MulVB src1 src2));
ins_cost(INSN_COST);
format %{ "mulv $dst,$src1,$src2\t# vector (16B)" %}
ins_encode %{
__ mulv(as_FloatRegister($dst$$reg), __ T16B,
as_FloatRegister($src1$$reg),
as_FloatRegister($src2$$reg));
%}
ins_pipe(vmul128);
%}
instruct vmul4S(vecD dst, vecD src1, vecD src2)
%{
predicate(n->as_Vector()->length() == 2 ||

@ -170,12 +170,12 @@ OopMap* RegisterSaver::save_live_registers(MacroAssembler* masm, int additional_
}
void RegisterSaver::restore_live_registers(MacroAssembler* masm, bool restore_vectors) {
#if COMPILER2_OR_JVMCI
__ pop_CPU_state(restore_vectors);
__ leave();
#else
#if !COMPILER2_OR_JVMCI
assert(!restore_vectors, "vectors are generated only by C2 and JVMCI");
#endif
__ pop_CPU_state(restore_vectors);
__ leave();
}
void RegisterSaver::restore_result_registers(MacroAssembler* masm) {

@ -58,9 +58,7 @@ ConstantPool* BytecodeConstantPool::create_constant_pool(TRAPS) const {
_orig->copy_cp_to(1, _orig->length() - 1, cp_h, 1, CHECK_NULL);
// Preserve dynamic constant information from the original pool
if (_orig->has_dynamic_constant()) {
cp->set_has_dynamic_constant();
}
cp->copy_fields(_orig);
for (int i = 0; i < _entries.length(); ++i) {
BytecodeCPEntry entry = _entries.at(i);

@ -315,7 +315,7 @@ void ShenandoahConcurrentMark::mark_roots(ShenandoahPhaseTimings::Phase root_pha
void ShenandoahConcurrentMark::update_roots(ShenandoahPhaseTimings::Phase root_phase) {
assert(ShenandoahSafepoint::is_at_shenandoah_safepoint(), "Must be at a safepoint");
assert(root_phase == ShenandoahPhaseTimings::full_gc_roots ||
assert(root_phase == ShenandoahPhaseTimings::full_gc_update_roots ||
root_phase == ShenandoahPhaseTimings::degen_gc_update_roots,
"Only for these phases");
@ -414,8 +414,6 @@ void ShenandoahConcurrentMark::mark_from_roots() {
WorkGang* workers = _heap->workers();
uint nworkers = workers->active_workers();
ShenandoahGCPhase conc_mark_phase(ShenandoahPhaseTimings::conc_mark);
if (_heap->process_references()) {
ReferenceProcessor* rp = _heap->ref_processor();
rp->set_active_mt_degree(nworkers);

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, 2019, Red Hat, Inc. All rights reserved.
* Copyright (c) 2013, 2020, Red Hat, Inc. 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
@ -242,6 +242,22 @@ void ShenandoahControlThread::run_service() {
heuristics->clear_metaspace_oom();
}
// Commit worker statistics to cycle data
heap->phase_timings()->flush_par_workers_to_cycle();
// Print GC stats for current cycle
{
LogTarget(Info, gc, stats) lt;
if (lt.is_enabled()) {
ResourceMark rm;
LogStream ls(lt);
heap->phase_timings()->print_cycle_on(&ls);
}
}
// Commit statistics to globals
heap->phase_timings()->flush_cycle_to_global();
// Print Metaspace change following GC (if logging is enabled).
MetaspaceUtils::print_metaspace_change(meta_sizes);
@ -265,6 +281,7 @@ void ShenandoahControlThread::run_service() {
current :
current - (ShenandoahUncommitDelay / 1000.0);
service_uncommit(shrink_before);
heap->phase_timings()->flush_cycle_to_global();
last_shrink_time = current;
}

@ -1190,7 +1190,7 @@ void ShenandoahHeap::print_tracing_info() const {
ResourceMark rm;
LogStream ls(lt);
phase_timings()->print_on(&ls);
phase_timings()->print_global_on(&ls);
ls.cr();
ls.cr();
@ -2198,20 +2198,14 @@ void ShenandoahHeap::stop() {
void ShenandoahHeap::stw_unload_classes(bool full_gc) {
if (!unload_classes()) return;
bool purged_class;
// Unload classes and purge SystemDictionary.
{
ShenandoahGCSubPhase phase(full_gc ?
ShenandoahPhaseTimings::full_gc_purge_class_unload :
ShenandoahPhaseTimings::purge_class_unload);
purged_class = SystemDictionary::do_unloading(gc_timer());
}
bool purged_class = SystemDictionary::do_unloading(gc_timer());
{
ShenandoahGCSubPhase phase(full_gc ?
ShenandoahPhaseTimings::full_gc_purge_par :
ShenandoahPhaseTimings::purge_par);
ShenandoahIsAliveSelector is_alive;
uint num_workers = _workers->active_workers();
ShenandoahClassUnloadingTask unlink_task(is_alive.is_alive_closure(), num_workers, purged_class);
@ -2239,8 +2233,8 @@ void ShenandoahHeap::stw_process_weak_roots(bool full_gc) {
ShenandoahPhaseTimings::purge);
uint num_workers = _workers->active_workers();
ShenandoahPhaseTimings::Phase timing_phase = full_gc ?
ShenandoahPhaseTimings::full_gc_purge_par :
ShenandoahPhaseTimings::purge_par;
ShenandoahPhaseTimings::full_gc_purge_weak_par :
ShenandoahPhaseTimings::purge_weak_par;
ShenandoahGCSubPhase phase(timing_phase);
ShenandoahGCWorkerPhase worker_phase(timing_phase);

@ -88,7 +88,7 @@ void ShenandoahMarkCompact::do_it(GCCause::Cause gc_cause) {
assert(Thread::current()->is_VM_thread(), "Do full GC only while world is stopped");
{
ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_heapdumps);
ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_heapdump_pre);
heap->pre_full_gc_dump(_gc_timer);
}
@ -204,7 +204,7 @@ void ShenandoahMarkCompact::do_it(GCCause::Cause gc_cause) {
}
{
ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_heapdumps);
ShenandoahGCPhase phase(ShenandoahPhaseTimings::full_gc_heapdump_post);
heap->post_full_gc_dump(_gc_timer);
}
}
@ -242,8 +242,8 @@ void ShenandoahMarkCompact::phase1_mark_heap() {
rp->setup_policy(true); // forcefully purge all soft references
rp->set_active_mt_degree(heap->workers()->active_workers());
cm->update_roots(ShenandoahPhaseTimings::full_gc_roots);
cm->mark_roots(ShenandoahPhaseTimings::full_gc_roots);
cm->update_roots(ShenandoahPhaseTimings::full_gc_update_roots);
cm->mark_roots(ShenandoahPhaseTimings::full_gc_scan_roots);
cm->finish_mark_from_roots(/* full_gc = */ true);
heap->mark_complete_marking_context();
heap->parallel_cleaning(true /* full_gc */);
@ -767,7 +767,7 @@ void ShenandoahMarkCompact::phase3_update_references() {
#if COMPILER2_OR_JVMCI
DerivedPointerTable::clear();
#endif
ShenandoahRootAdjuster rp(nworkers, ShenandoahPhaseTimings::full_gc_roots);
ShenandoahRootAdjuster rp(nworkers, ShenandoahPhaseTimings::full_gc_adjust_roots);
ShenandoahAdjustRootPointersTask task(&rp, _preserved_marks);
workers->run_task(&task);
#if COMPILER2_OR_JVMCI

@ -30,8 +30,14 @@
#include "gc/shenandoah/shenandoahHeap.hpp"
#include "gc/shenandoah/shenandoahHeuristics.hpp"
#include "gc/shenandoah/shenandoahUtils.hpp"
#include "runtime/orderAccess.hpp"
#include "utilities/ostream.hpp"
#define SHENANDOAH_PHASE_NAME_FORMAT "%-28s"
#define SHENANDOAH_S_TIME_FORMAT "%8.3lf"
#define SHENANDOAH_US_TIME_FORMAT "%8.0lf"
#define SHENANDOAH_US_WORKER_TIME_FORMAT "%3.0lf"
#define GC_PHASE_DECLARE_NAME(type, title) \
title,
@ -42,58 +48,155 @@ const char* ShenandoahPhaseTimings::_phase_names[] = {
#undef GC_PHASE_DECLARE_NAME
ShenandoahPhaseTimings::ShenandoahPhaseTimings() {
uint max_workers = MAX2(ConcGCThreads, ParallelGCThreads);
assert(max_workers > 0, "Must have some GC threads");
_max_workers = MAX2(ConcGCThreads, ParallelGCThreads);
assert(_max_workers > 0, "Must have some GC threads");
#define GC_PAR_PHASE_DECLARE_WORKER_DATA(type, title) \
_gc_par_phases[ShenandoahPhaseTimings::type] = new WorkerDataArray<double>(title, max_workers);
// Root scanning phases
SHENANDOAH_GC_PAR_PHASE_DO(,, GC_PAR_PHASE_DECLARE_WORKER_DATA)
#undef GC_PAR_PHASE_DECLARE_WORKER_DATA
// Initialize everything to sane defaults
for (uint i = 0; i < _num_phases; i++) {
#define SHENANDOAH_WORKER_DATA_NULL(type, title) \
_worker_data[i] = NULL;
SHENANDOAH_GC_PAR_PHASE_DO(,, SHENANDOAH_WORKER_DATA_NULL)
#undef SHENANDOAH_WORKER_DATA_NULL
_cycle_data[i] = 0;
}
// Then punch in the worker-related data.
// Every worker phase get a bunch of internal objects, except
// the very first slot, which is "<total>" and is not populated.
for (uint i = 0; i < _num_phases; i++) {
if (is_worker_phase(Phase(i))) {
int c = 0;
#define SHENANDOAH_WORKER_DATA_INIT(type, title) \
if (c++ != 0) _worker_data[i + c] = new ShenandoahWorkerData(title, _max_workers);
SHENANDOAH_GC_PAR_PHASE_DO(,, SHENANDOAH_WORKER_DATA_INIT)
#undef SHENANDOAH_WORKER_DATA_INIT
}
}
_policy = ShenandoahHeap::heap()->shenandoah_policy();
assert(_policy != NULL, "Can not be NULL");
_current_worker_phase = _invalid_phase;
}
ShenandoahPhaseTimings::Phase ShenandoahPhaseTimings::worker_par_phase(Phase phase, GCParPhases par_phase) {
assert(is_worker_phase(phase), "Phase should accept worker phase times: %s", phase_name(phase));
Phase p = Phase(phase + 1 + par_phase);
assert(p >= 0 && p < _num_phases, "Out of bound for: %s", phase_name(phase));
return p;
}
ShenandoahWorkerData* ShenandoahPhaseTimings::worker_data(Phase phase, GCParPhases par_phase) {
Phase p = worker_par_phase(phase, par_phase);
ShenandoahWorkerData* wd = _worker_data[p];
assert(wd != NULL, "Counter initialized: %s", phase_name(p));
return wd;
}
bool ShenandoahPhaseTimings::is_worker_phase(Phase phase) {
assert(phase >= 0 && phase < _num_phases, "Out of bounds");
switch (phase) {
case init_evac:
case scan_roots:
case update_roots:
case final_update_refs_roots:
case full_gc_scan_roots:
case full_gc_update_roots:
case full_gc_adjust_roots:
case degen_gc_update_roots:
case full_gc_purge_class_unload:
case full_gc_purge_weak_par:
case purge_class_unload:
case purge_weak_par:
case heap_iteration_roots:
return true;
default:
return false;
}
}
void ShenandoahPhaseTimings::set_cycle_data(Phase phase, double time) {
#ifdef ASSERT
double d = _cycle_data[phase];
assert(d == 0, "Should not be set yet: %s, current value: %lf", phase_name(phase), d);
#endif
_cycle_data[phase] = time;
}
void ShenandoahPhaseTimings::record_phase_time(Phase phase, double time) {
if (!_policy->is_at_shutdown()) {
_timing_data[phase].add(time);
set_cycle_data(phase, time);
}
}
void ShenandoahPhaseTimings::record_workers_start(Phase phase) {
for (uint i = 0; i < GCParPhasesSentinel; i++) {
_gc_par_phases[i]->reset();
assert(is_worker_phase(phase), "Phase should accept worker phase times: %s", phase_name(phase));
assert(_current_worker_phase == _invalid_phase, "Should not be set yet: requested %s, existing %s",
phase_name(phase), phase_name(_current_worker_phase));
_current_worker_phase = phase;
for (uint i = 1; i < GCParPhasesSentinel; i++) {
worker_data(phase, GCParPhases(i))->reset();
}
}
void ShenandoahPhaseTimings::record_workers_end(Phase phase) {
if (_policy->is_at_shutdown()) {
// Do not record the past-shutdown events
return;
}
assert(phase == init_evac ||
phase == scan_roots ||
phase == update_roots ||
phase == final_update_refs_roots ||
phase == full_gc_roots ||
phase == degen_gc_update_roots ||
phase == full_gc_purge_par ||
phase == purge_par ||
phase == heap_iteration_roots,
"Phase should accept accept per-thread phase times: %s", phase_name(phase));
double s = 0;
for (uint i = 1; i < GCParPhasesSentinel; i++) {
double t = _gc_par_phases[i]->sum();
_timing_data[phase + i + 1].add(t); // add to each line in phase
s += t;
}
_timing_data[phase + 1].add(s); // add to total for phase
assert(is_worker_phase(phase), "Phase should accept worker phase times: %s", phase_name(phase));
_current_worker_phase = _invalid_phase;
}
void ShenandoahPhaseTimings::print_on(outputStream* out) const {
void ShenandoahPhaseTimings::flush_par_workers_to_cycle() {
for (uint pi = 0; pi < _num_phases; pi++) {
Phase phase = Phase(pi);
if (is_worker_phase(phase)) {
double s = 0;
for (uint i = 1; i < GCParPhasesSentinel; i++) {
double t = worker_data(phase, GCParPhases(i))->sum();
// add to each line in phase
set_cycle_data(Phase(phase + i + 1), t);
s += t;
}
// add to total for phase
set_cycle_data(Phase(phase + 1), s);
}
}
}
void ShenandoahPhaseTimings::flush_cycle_to_global() {
for (uint i = 0; i < _num_phases; i++) {
_global_data[i].add(_cycle_data[i]);
_cycle_data[i] = 0;
}
OrderAccess::fence();
}
void ShenandoahPhaseTimings::print_cycle_on(outputStream* out) const {
out->cr();
out->print_cr("All times are wall-clock times, except per-root-class counters, that are sum over");
out->print_cr("all workers. Dividing the <total> over the root stage time estimates parallelism.");
out->cr();
for (uint i = 0; i < _num_phases; i++) {
double v = _cycle_data[i] * 1000000.0;
if (v > 0) {
out->print(SHENANDOAH_PHASE_NAME_FORMAT " " SHENANDOAH_US_TIME_FORMAT " us", _phase_names[i], v);
if (_worker_data[i] != NULL) {
out->print(", workers (us): ");
for (size_t c = 0; c < _max_workers; c++) {
double tv = _worker_data[i]->get(c);
if (tv != ShenandoahWorkerData::uninitialized()) {
out->print(SHENANDOAH_US_WORKER_TIME_FORMAT ", ", tv * 1000000.0);
} else {
out->print("%3s, ", "---");
}
}
}
out->cr();
}
}
}
void ShenandoahPhaseTimings::print_global_on(outputStream* out) const {
out->cr();
out->print_cr("GC STATISTICS:");
out->print_cr(" \"(G)\" (gross) pauses include VM time: time to notify and block threads, do the pre-");
@ -107,37 +210,43 @@ void ShenandoahPhaseTimings::print_on(outputStream* out) const {
out->cr();
for (uint i = 0; i < _num_phases; i++) {
if (_timing_data[i].maximum() != 0) {
out->print_cr("%-27s = %8.2lf s (a = %8.0lf us) (n = " INT32_FORMAT_W(5) ") (lvls, us = %8.0lf, %8.0lf, %8.0lf, %8.0lf, %8.0lf)",
if (_global_data[i].maximum() != 0) {
out->print_cr(SHENANDOAH_PHASE_NAME_FORMAT " = " SHENANDOAH_S_TIME_FORMAT " s "
"(a = " SHENANDOAH_US_TIME_FORMAT " us) "
"(n = " INT32_FORMAT_W(5) ") (lvls, us = "
SHENANDOAH_US_TIME_FORMAT ", "
SHENANDOAH_US_TIME_FORMAT ", "
SHENANDOAH_US_TIME_FORMAT ", "
SHENANDOAH_US_TIME_FORMAT ", "
SHENANDOAH_US_TIME_FORMAT ")",
_phase_names[i],
_timing_data[i].sum(),
_timing_data[i].avg() * 1000000.0,
_timing_data[i].num(),
_timing_data[i].percentile(0) * 1000000.0,
_timing_data[i].percentile(25) * 1000000.0,
_timing_data[i].percentile(50) * 1000000.0,
_timing_data[i].percentile(75) * 1000000.0,
_timing_data[i].maximum() * 1000000.0
_global_data[i].sum(),
_global_data[i].avg() * 1000000.0,
_global_data[i].num(),
_global_data[i].percentile(0) * 1000000.0,
_global_data[i].percentile(25) * 1000000.0,
_global_data[i].percentile(50) * 1000000.0,
_global_data[i].percentile(75) * 1000000.0,
_global_data[i].maximum() * 1000000.0
);
}
}
}
void ShenandoahPhaseTimings::record_worker_time(ShenandoahPhaseTimings::GCParPhases phase, uint worker_id, double secs) {
_gc_par_phases[phase]->set(worker_id, secs);
}
ShenandoahWorkerTimingsTracker::ShenandoahWorkerTimingsTracker(ShenandoahPhaseTimings::GCParPhases phase, uint worker_id) :
_phase(phase), _timings(ShenandoahHeap::heap()->phase_timings()), _worker_id(worker_id) {
ShenandoahWorkerTimingsTracker::ShenandoahWorkerTimingsTracker(ShenandoahPhaseTimings::GCParPhases par_phase, uint worker_id) :
_timings(ShenandoahHeap::heap()->phase_timings()), _phase(_timings->current_worker_phase()),
_par_phase(par_phase), _worker_id(worker_id) {
assert(_timings->worker_data(_phase, _par_phase)->get(_worker_id) == ShenandoahWorkerData::uninitialized(),
"Should not be set yet: %s", ShenandoahPhaseTimings::phase_name(_timings->worker_par_phase(_phase, _par_phase)));
_start_time = os::elapsedTime();
}
ShenandoahWorkerTimingsTracker::~ShenandoahWorkerTimingsTracker() {
_timings->record_worker_time(_phase, _worker_id, os::elapsedTime() - _start_time);
_timings->worker_data(_phase, _par_phase)->set(_worker_id, os::elapsedTime() - _start_time);
if (ShenandoahGCPhase::is_root_work_phase()) {
ShenandoahPhaseTimings::Phase root_phase = ShenandoahGCPhase::current_phase();
ShenandoahPhaseTimings::Phase cur_phase = (ShenandoahPhaseTimings::Phase)((int)root_phase + (int)_phase + 1);
ShenandoahPhaseTimings::Phase cur_phase = _timings->worker_par_phase(root_phase, _par_phase);
_event.commit(GCId::current(), _worker_id, ShenandoahPhaseTimings::phase_name(cur_phase));
}
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 2017, 2019, Red Hat, Inc. All rights reserved.
* Copyright (c) 2017, 2020, Red Hat, Inc. 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
@ -79,8 +79,9 @@ class outputStream;
f(weakrefs_process, " Process") \
f(purge, " System Purge") \
f(purge_class_unload, " Unload Classes") \
f(purge_par, " Parallel Cleanup") \
SHENANDOAH_GC_PAR_PHASE_DO(purge_par_roots, " PC: ", f) \
SHENANDOAH_GC_PAR_PHASE_DO(purge_cu_par_, " CU: ", f) \
f(purge_weak_par, " Weak Roots") \
SHENANDOAH_GC_PAR_PHASE_DO(purge_weak_par_, " WR: ", f) \
f(purge_cldg, " CLDG") \
f(final_update_region_states, " Update Region States") \
f(retire_tlabs, " Retire TLABs") \
@ -119,29 +120,35 @@ class outputStream;
\
f(full_gc_gross, "Pause Full GC (G)") \
f(full_gc, "Pause Full GC (N)") \
f(full_gc_heapdumps, " Heap Dumps") \
f(full_gc_heapdump_pre, " Pre Heap Dump") \
f(full_gc_prepare, " Prepare") \
f(full_gc_roots, " Roots") \
SHENANDOAH_GC_PAR_PHASE_DO(full_gc_, " F: ", f) \
f(full_gc_scan_roots, " Scan Roots") \
SHENANDOAH_GC_PAR_PHASE_DO(full_gc_scan_roots_, " FS: ", f) \
f(full_gc_update_roots, " Update Roots") \
SHENANDOAH_GC_PAR_PHASE_DO(full_gc_update_roots_, " FU: ", f) \
f(full_gc_mark, " Mark") \
f(full_gc_mark_finish_queues, " Finish Queues") \
f(full_gc_weakrefs, " Weak References") \
f(full_gc_weakrefs_process, " Process") \
f(full_gc_purge, " System Purge") \
f(full_gc_purge_class_unload, " Unload Classes") \
f(full_gc_purge_par, " Parallel Cleanup") \
SHENANDOAH_GC_PAR_PHASE_DO(full_gc_purge_roots, " PC: ", f) \
f(full_gc_purge_cldg, " CLDG") \
SHENANDOAH_GC_PAR_PHASE_DO(full_gc_purge_cu_par_, " CU: ", f) \
f(full_gc_purge_weak_par, " Weak Roots") \
SHENANDOAH_GC_PAR_PHASE_DO(full_gc_purge_weak_p_, " WR: ", f) \
f(full_gc_purge_cldg, " CLDG") \
f(full_gc_calculate_addresses, " Calculate Addresses") \
f(full_gc_calculate_addresses_regular, " Regular Objects") \
f(full_gc_calculate_addresses_humong, " Humongous Objects") \
f(full_gc_adjust_pointers, " Adjust Pointers") \
f(full_gc_adjust_roots, " Adjust Roots") \
SHENANDOAH_GC_PAR_PHASE_DO(full_gc_adjust_roots_, " FA: ", f) \
f(full_gc_copy_objects, " Copy Objects") \
f(full_gc_copy_objects_regular, " Regular Objects") \
f(full_gc_copy_objects_humong, " Humongous Objects") \
f(full_gc_copy_objects_reset_complete, " Reset Complete Bitmap") \
f(full_gc_copy_objects_rebuild, " Rebuild Region Sets") \
f(full_gc_resize_tlabs, " Resize TLABs") \
f(full_gc_heapdump_post, " Post Heap Dump") \
\
f(conc_uncommit, "Concurrent Uncommit") \
\
@ -149,7 +156,11 @@ class outputStream;
SHENANDOAH_GC_PAR_PHASE_DO(heap_iteration_roots_, " HI: ", f) \
// end
typedef WorkerDataArray<double> ShenandoahWorkerData;
class ShenandoahPhaseTimings : public CHeapObj<mtGC> {
friend class ShenandoahGCPhase;
friend class ShenandoahWorkerTimingsTracker;
public:
#define GC_PHASE_DECLARE_ENUM(type, title) type,
@ -167,39 +178,54 @@ public:
#undef GC_PHASE_DECLARE_ENUM
private:
HdrSeq _timing_data[_num_phases];
size_t _max_workers;
double _cycle_data[_num_phases];
HdrSeq _global_data[_num_phases];
static const char* _phase_names[_num_phases];
WorkerDataArray<double>* _gc_par_phases[ShenandoahPhaseTimings::GCParPhasesSentinel];
Phase _current_worker_phase;
ShenandoahWorkerData* _worker_data[_num_phases];
ShenandoahCollectorPolicy* _policy;
static bool is_worker_phase(Phase phase);
Phase current_worker_phase() { return _current_worker_phase; }
ShenandoahWorkerData* worker_data(Phase phase, GCParPhases par_phase);
Phase worker_par_phase(Phase phase, GCParPhases par_phase);
void set_cycle_data(Phase phase, double time);
public:
ShenandoahPhaseTimings();
void record_phase_time(Phase phase, double time);
void record_worker_time(GCParPhases phase, uint worker_id, double time);
void record_workers_start(Phase phase);
void record_workers_end(Phase phase);
void flush_par_workers_to_cycle();
void flush_cycle_to_global();
static const char* phase_name(Phase phase) {
assert(phase >= 0 && phase < _num_phases, "Out of bound");
return _phase_names[phase];
}
void print_on(outputStream* out) const;
void print_cycle_on(outputStream* out) const;
void print_global_on(outputStream* out) const;
};
class ShenandoahWorkerTimingsTracker : public StackObj {
private:
ShenandoahPhaseTimings::GCParPhases const _phase;
ShenandoahPhaseTimings* const _timings;
ShenandoahPhaseTimings* const _timings;
ShenandoahPhaseTimings::Phase const _phase;
ShenandoahPhaseTimings::GCParPhases const _par_phase;
uint const _worker_id;
double _start_time;
EventGCPhaseParallel _event;
public:
ShenandoahWorkerTimingsTracker(ShenandoahPhaseTimings::GCParPhases phase, uint worker_id);
ShenandoahWorkerTimingsTracker(ShenandoahPhaseTimings::GCParPhases par_phase, uint worker_id);
~ShenandoahWorkerTimingsTracker();
};

@ -132,7 +132,9 @@ bool ShenandoahGCPhase::is_root_work_phase() {
case ShenandoahPhaseTimings::init_evac:
case ShenandoahPhaseTimings::final_update_refs_roots:
case ShenandoahPhaseTimings::degen_gc_update_roots:
case ShenandoahPhaseTimings::full_gc_roots:
case ShenandoahPhaseTimings::full_gc_scan_roots:
case ShenandoahPhaseTimings::full_gc_update_roots:
case ShenandoahPhaseTimings::full_gc_adjust_roots:
return true;
default:
return false;

@ -287,12 +287,14 @@ void ZPageAllocator::increase_used(size_t size, bool relocation) {
}
void ZPageAllocator::decrease_used(size_t size, bool reclaimed) {
// Only pages explicitly released with the reclaimed flag set
// counts as reclaimed bytes. This flag is true when we release
// a page after relocation, and is false when we release a page
// to undo an allocation.
if (reclaimed) {
// Only pages explicitly released with the reclaimed flag set
// counts as reclaimed bytes. This flag is typically true when
// a worker releases a page after relocation, and is typically
// false when we release a page to undo an allocation.
_reclaimed += size;
} else {
_allocated -= size;
}
_used -= size;
if (_used < _used_low) {

@ -116,7 +116,8 @@
nonstatic_field(ConstantPool, _tags, Array<u1>*) \
nonstatic_field(ConstantPool, _pool_holder, InstanceKlass*) \
nonstatic_field(ConstantPool, _length, int) \
nonstatic_field(ConstantPool, _flags, int) \
nonstatic_field(ConstantPool, _flags, u2) \
nonstatic_field(ConstantPool, _source_file_name_index, u2) \
\
nonstatic_field(ConstMethod, _constants, ConstantPool*) \
nonstatic_field(ConstMethod, _flags, u2) \
@ -155,10 +156,9 @@
\
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
nonstatic_field(InstanceKlass, _source_file_name_index, u2) \
nonstatic_field(InstanceKlass, _init_state, u1) \
nonstatic_field(InstanceKlass, _init_thread, Thread*) \
nonstatic_field(InstanceKlass, _misc_flags, u4) \
nonstatic_field(InstanceKlass, _misc_flags, u2) \
nonstatic_field(InstanceKlass, _annotations, Annotations*) \
\
volatile_nonstatic_field(JavaFrameAnchor, _last_Java_sp, intptr_t*) \

@ -65,6 +65,20 @@ ConstantPool* ConstantPool::allocate(ClassLoaderData* loader_data, int length, T
return new (loader_data, size, MetaspaceObj::ConstantPoolType, THREAD) ConstantPool(tags);
}
void ConstantPool::copy_fields(const ConstantPool* orig) {
// Preserve dynamic constant information from the original pool
if (orig->has_dynamic_constant()) {
set_has_dynamic_constant();
}
// Copy class version
set_major_version(orig->major_version());
set_minor_version(orig->minor_version());
set_source_file_name_index(orig->source_file_name_index());
set_generic_signature_index(orig->generic_signature_index());
}
#ifdef ASSERT
// MetaspaceObj allocation invariant is calloc equivalent memory

@ -110,6 +110,16 @@ class ConstantPool : public Metadata {
// save space on 64-bit platforms.
Array<Klass*>* _resolved_klasses;
u2 _major_version; // major version number of class file
u2 _minor_version; // minor version number of class file
// Constant pool index to the utf8 entry of the Generic signature,
// or 0 if none.
u2 _generic_signature_index;
// Constant pool index to the utf8 entry for the name of source file
// containing this klass, 0 if not specified.
u2 _source_file_name_index;
enum {
_has_preresolution = 1, // Flags
_on_stack = 2,
@ -117,8 +127,9 @@ class ConstantPool : public Metadata {
_has_dynamic_constant = 8
};
int _flags; // old fashioned bit twiddling
int _length; // number of elements in the array
u2 _flags; // old fashioned bit twiddling
int _length; // number of elements in the array
union {
// set for CDS to restore resolved references
@ -135,8 +146,8 @@ class ConstantPool : public Metadata {
void set_operands(Array<u2>* operands) { _operands = operands; }
int flags() const { return _flags; }
void set_flags(int f) { _flags = f; }
u2 flags() const { return _flags; }
void set_flags(u2 f) { _flags = f; }
private:
intptr_t* base() const { return (intptr_t*) (((char*) this) + sizeof(ConstantPool)); }
@ -189,6 +200,30 @@ class ConstantPool : public Metadata {
_flags |= _has_preresolution;
}
// minor and major version numbers of class file
u2 major_version() const { return _major_version; }
void set_major_version(u2 major_version) { _major_version = major_version; }
u2 minor_version() const { return _minor_version; }
void set_minor_version(u2 minor_version) { _minor_version = minor_version; }
// generics support
Symbol* generic_signature() const {
return (_generic_signature_index == 0) ?
(Symbol*)NULL : symbol_at(_generic_signature_index);
}
u2 generic_signature_index() const { return _generic_signature_index; }
void set_generic_signature_index(u2 sig_index) { _generic_signature_index = sig_index; }
// source file name
Symbol* source_file_name() const {
return (_source_file_name_index == 0) ?
(Symbol*)NULL : symbol_at(_source_file_name_index);
}
u2 source_file_name_index() const { return _source_file_name_index; }
void set_source_file_name_index(u2 sourcefile_index) { _source_file_name_index = sourcefile_index; }
void copy_fields(const ConstantPool* orig);
// Redefine classes support. If a method refering to this constant pool
// is on the executing stack, or as a handle in vm code, this constant pool
// can't be removed from the set of previous versions saved in the instance

@ -43,7 +43,7 @@ public:
static const KlassID ID = InstanceClassLoaderKlassID;
private:
InstanceClassLoaderKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_misc_kind_class_loader, ID) {}
InstanceClassLoaderKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_kind_class_loader, ID) {}
public:
InstanceClassLoaderKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }

@ -442,7 +442,7 @@ InstanceKlass* InstanceKlass::allocate_instance_klass(const ClassFileParser& par
ik = new (loader_data, size, THREAD) InstanceClassLoaderKlass(parser);
} else {
// normal
ik = new (loader_data, size, THREAD) InstanceKlass(parser, InstanceKlass::_misc_kind_other);
ik = new (loader_data, size, THREAD) InstanceKlass(parser, InstanceKlass::_kind_other);
}
} else {
// reference
@ -483,15 +483,15 @@ Array<int>* InstanceKlass::create_new_default_vtable_indices(int len, TRAPS) {
InstanceKlass::InstanceKlass(const ClassFileParser& parser, unsigned kind, KlassID id) :
Klass(id),
_nest_members(NULL),
_nest_host_index(0),
_nest_host(NULL),
_record_components(NULL),
_static_field_size(parser.static_field_size()),
_nonstatic_oop_map_size(nonstatic_oop_map_size(parser.total_oop_map_count())),
_itable_len(parser.itable_size()),
_init_thread(NULL),
_nest_host_index(0),
_init_state(allocated),
_reference_type(parser.reference_type())
_reference_type(parser.reference_type()),
_init_thread(NULL)
{
set_vtable_length(parser.vtable_size());
set_kind(kind);

@ -191,10 +191,6 @@ class InstanceKlass: public Klass {
// has not been validated.
Array<jushort>* _nest_members;
// The NestHost attribute. The class info index for the class
// that is the nest-host of this class. This data has not been validated.
jushort _nest_host_index;
// Resolved nest-host klass: either true nest-host or self if we are not
// nested, or an error occurred resolving or validating the nominated
// nest-host. Can also be set directly by JDK API's that establish nest
@ -217,60 +213,63 @@ class InstanceKlass: public Klass {
// (including inherited fields but after header_size()).
int _nonstatic_field_size;
int _static_field_size; // number words used by static fields (oop and non-oop) in this klass
// Constant pool index to the utf8 entry of the Generic signature,
// or 0 if none.
u2 _generic_signature_index;
// Constant pool index to the utf8 entry for the name of source file
// containing this klass, 0 if not specified.
u2 _source_file_name_index;
int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
int _itable_len; // length of Java itable (in words)
// The NestHost attribute. The class info index for the class
// that is the nest-host of this class. This data has not been validated.
u2 _nest_host_index;
u2 _this_class_index; // constant pool entry
u2 _static_oop_field_count;// number of static oop fields in this klass
u2 _java_fields_count; // The number of declared Java fields
int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
int _itable_len; // length of Java itable (in words)
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
// _is_marked_dependent can be set concurrently, thus cannot be part of the
// _misc_flags.
bool _is_marked_dependent; // used for marking during flushing and deoptimization
// The low two bits of _misc_flags contains the kind field.
// Class states are defined as ClassState (see above).
// Place the _init_state here to utilize the unused 2-byte after
// _idnum_allocated_count.
u1 _init_state; // state of class
// This can be used to quickly discriminate among the four kinds of
// InstanceKlass.
// InstanceKlass. This should be an enum (?)
static const unsigned _kind_other = 0; // concrete InstanceKlass
static const unsigned _kind_reference = 1; // InstanceRefKlass
static const unsigned _kind_class_loader = 2; // InstanceClassLoaderKlass
static const unsigned _kind_mirror = 3; // InstanceMirrorKlass
static const unsigned _misc_kind_field_size = 2;
static const unsigned _misc_kind_field_pos = 0;
static const unsigned _misc_kind_field_mask = (1u << _misc_kind_field_size) - 1u;
u1 _reference_type; // reference type
u1 _kind; // kind of InstanceKlass
static const unsigned _misc_kind_other = 0; // concrete InstanceKlass
static const unsigned _misc_kind_reference = 1; // InstanceRefKlass
static const unsigned _misc_kind_class_loader = 2; // InstanceClassLoaderKlass
static const unsigned _misc_kind_mirror = 3; // InstanceMirrorKlass
// Start after _misc_kind field.
enum {
_misc_rewritten = 1 << 2, // methods rewritten.
_misc_has_nonstatic_fields = 1 << 3, // for sizing with UseCompressedOops
_misc_should_verify_class = 1 << 4, // allow caching of preverification
_misc_is_unsafe_anonymous = 1 << 5, // has embedded _unsafe_anonymous_host field
_misc_is_contended = 1 << 6, // marked with contended annotation
_misc_has_nonstatic_concrete_methods = 1 << 7, // class/superclass/implemented interfaces has non-static, concrete methods
_misc_declares_nonstatic_concrete_methods = 1 << 8, // directly declares non-static, concrete methods
_misc_has_been_redefined = 1 << 9, // class has been redefined
_misc_has_passed_fingerprint_check = 1 << 10, // when this class was loaded, the fingerprint computed from its
_misc_rewritten = 1 << 0, // methods rewritten.
_misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops
_misc_should_verify_class = 1 << 2, // allow caching of preverification
_misc_is_unsafe_anonymous = 1 << 3, // has embedded _unsafe_anonymous_host field
_misc_is_contended = 1 << 4, // marked with contended annotation
_misc_has_nonstatic_concrete_methods = 1 << 5, // class/superclass/implemented interfaces has non-static, concrete methods
_misc_declares_nonstatic_concrete_methods = 1 << 6, // directly declares non-static, concrete methods
_misc_has_been_redefined = 1 << 7, // class has been redefined
_misc_has_passed_fingerprint_check = 1 << 8, // when this class was loaded, the fingerprint computed from its
// code source was found to be matching the value recorded by AOT.
_misc_is_scratch_class = 1 << 11, // class is the redefined scratch class
_misc_is_shared_boot_class = 1 << 12, // defining class loader is boot class loader
_misc_is_shared_platform_class = 1 << 13, // defining class loader is platform class loader
_misc_is_shared_app_class = 1 << 14, // defining class loader is app class loader
_misc_has_resolved_methods = 1 << 15, // resolved methods table entries added for this class
_misc_is_being_redefined = 1 << 16, // used for locking redefinition
_misc_has_contended_annotations = 1 << 17 // has @Contended annotation
_misc_is_scratch_class = 1 << 9, // class is the redefined scratch class
_misc_is_shared_boot_class = 1 << 10, // defining class loader is boot class loader
_misc_is_shared_platform_class = 1 << 11, // defining class loader is platform class loader
_misc_is_shared_app_class = 1 << 12, // defining class loader is app class loader
_misc_has_resolved_methods = 1 << 13, // resolved methods table entries added for this class
_misc_is_being_redefined = 1 << 14, // used for locking redefinition
_misc_has_contended_annotations = 1 << 15 // has @Contended annotation
};
u2 shared_loader_type_bits() const {
return _misc_is_shared_boot_class|_misc_is_shared_platform_class|_misc_is_shared_app_class;
}
u4 _misc_flags;
u2 _minor_version; // minor version number of class file
u2 _major_version; // major version number of class file
u2 _misc_flags; // There is more space in access_flags for more flags.
Thread* _init_thread; // Pointer to current thread doing initialization (to handle recursive initialization)
OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily)
JNIid* _jni_ids; // First JNI identifier for static fields in this class
@ -287,15 +286,6 @@ class InstanceKlass: public Klass {
JvmtiCachedClassFileData* _cached_class_file;
#endif
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
// Class states are defined as ClassState (see above).
// Place the _init_state here to utilize the unused 2-byte after
// _idnum_allocated_count.
u1 _init_state; // state of class
u1 _reference_type; // reference type
u2 _this_class_index; // constant pool entry
#if INCLUDE_JVMTI
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration
#endif
@ -730,22 +720,15 @@ public:
}
// source file name
Symbol* source_file_name() const {
return (_source_file_name_index == 0) ?
(Symbol*)NULL : _constants->symbol_at(_source_file_name_index);
}
u2 source_file_name_index() const {
return _source_file_name_index;
}
void set_source_file_name_index(u2 sourcefile_index) {
_source_file_name_index = sourcefile_index;
}
Symbol* source_file_name() const { return _constants->source_file_name(); }
u2 source_file_name_index() const { return _constants->source_file_name_index(); }
void set_source_file_name_index(u2 sourcefile_index) { _constants->set_source_file_name_index(sourcefile_index); }
// minor and major version numbers of class file
u2 minor_version() const { return _minor_version; }
void set_minor_version(u2 minor_version) { _minor_version = minor_version; }
u2 major_version() const { return _major_version; }
void set_major_version(u2 major_version) { _major_version = major_version; }
u2 minor_version() const { return _constants->minor_version(); }
void set_minor_version(u2 minor_version) { _constants->set_minor_version(minor_version); }
u2 major_version() const { return _constants->major_version(); }
void set_major_version(u2 major_version) { _constants->set_major_version(major_version); }
// source debug extension
const char* source_debug_extension() const { return _source_debug_extension; }
@ -852,24 +835,20 @@ public:
private:
void set_kind(unsigned kind) {
assert(kind <= _misc_kind_field_mask, "Invalid InstanceKlass kind");
unsigned fmask = _misc_kind_field_mask << _misc_kind_field_pos;
unsigned flags = _misc_flags & ~fmask;
_misc_flags = (flags | (kind << _misc_kind_field_pos));
_kind = (u1)kind;
}
bool is_kind(unsigned desired) const {
unsigned kind = (_misc_flags >> _misc_kind_field_pos) & _misc_kind_field_mask;
return kind == desired;
return _kind == (u1)desired;
}
public:
// Other is anything that is not one of the more specialized kinds of InstanceKlass.
bool is_other_instance_klass() const { return is_kind(_misc_kind_other); }
bool is_reference_instance_klass() const { return is_kind(_misc_kind_reference); }
bool is_mirror_instance_klass() const { return is_kind(_misc_kind_mirror); }
bool is_class_loader_instance_klass() const { return is_kind(_misc_kind_class_loader); }
bool is_other_instance_klass() const { return is_kind(_kind_other); }
bool is_reference_instance_klass() const { return is_kind(_kind_reference); }
bool is_mirror_instance_klass() const { return is_kind(_kind_mirror); }
bool is_class_loader_instance_klass() const { return is_kind(_kind_class_loader); }
#if INCLUDE_JVMTI
@ -943,16 +922,9 @@ public:
void set_initial_method_idnum(u2 value) { _idnum_allocated_count = value; }
// generics support
Symbol* generic_signature() const {
return (_generic_signature_index == 0) ?
(Symbol*)NULL : _constants->symbol_at(_generic_signature_index);
}
u2 generic_signature_index() const {
return _generic_signature_index;
}
void set_generic_signature_index(u2 sig_index) {
_generic_signature_index = sig_index;
}
Symbol* generic_signature() const { return _constants->generic_signature(); }
u2 generic_signature_index() const { return _constants->generic_signature_index(); }
void set_generic_signature_index(u2 sig_index) { _constants->set_generic_signature_index(sig_index); }
u2 enclosing_method_data(int offset) const;
u2 enclosing_method_class_index() const {

@ -50,7 +50,7 @@ class InstanceMirrorKlass: public InstanceKlass {
private:
static int _offset_of_static_fields;
InstanceMirrorKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_misc_kind_mirror, ID) {}
InstanceMirrorKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_kind_mirror, ID) {}
public:
InstanceMirrorKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }

@ -53,7 +53,7 @@ class InstanceRefKlass: public InstanceKlass {
static const KlassID ID = InstanceRefKlassID;
private:
InstanceRefKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_misc_kind_reference, ID) {}
InstanceRefKlass(const ClassFileParser& parser) : InstanceKlass(parser, InstanceKlass::_kind_reference, ID) {}
public:
InstanceRefKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }

@ -117,6 +117,9 @@ class Klass : public Metadata {
// Klass identifier used to implement devirtualized oop closure dispatching.
const KlassID _id;
// vtable length
int _vtable_len;
// The fields _super_check_offset, _secondary_super_cache, _secondary_supers
// and _primary_supers all help make fast subtype checks. See big discussion
// in doc/server_compiler/checktype.txt
@ -136,7 +139,7 @@ class Klass : public Metadata {
// Ordered list of all primary supertypes
Klass* _primary_supers[_primary_super_limit];
// java/lang/Class instance mirroring this class
OopHandle _java_mirror;
OopHandle _java_mirror;
// Superclass
Klass* _super;
// First subclass (NULL if none); _subklass->next_sibling() is next one
@ -162,9 +165,6 @@ class Klass : public Metadata {
markWord _prototype_header; // Used when biased locking is both enabled and disabled for this type
jint _biased_lock_revocation_count;
// vtable length
int _vtable_len;
private:
// This is an index into FileMapHeader::_shared_path_table[], to
// associate this class with the JAR file where it's loaded from during
@ -179,6 +179,7 @@ private:
_has_raw_archived_mirror = 1
};
#endif
// The _archived_mirror is set at CDS dump time pointing to the cached mirror
// in the open archive heap region when archiving java object is supported.
CDS_JAVA_HEAP_ONLY(narrowOop _archived_mirror;)

@ -1432,6 +1432,7 @@ methodHandle Method::make_method_handle_intrinsic(vmIntrinsics::ID iid,
ConstantPool* cp_oop = ConstantPool::allocate(loader_data, cp_length, CHECK_(empty));
cp = constantPoolHandle(THREAD, cp_oop);
}
cp->copy_fields(holder->constants());
cp->set_pool_holder(holder);
cp->symbol_at_put(_imcp_invoke_name, name);
cp->symbol_at_put(_imcp_invoke_signature, signature);

@ -1699,10 +1699,9 @@ jvmtiError VM_RedefineClasses::merge_cp_and_rewrite(
return JVMTI_ERROR_INTERNAL;
}
if (old_cp->has_dynamic_constant()) {
merge_cp->set_has_dynamic_constant();
scratch_cp->set_has_dynamic_constant();
}
// Save fields from the old_cp.
merge_cp->copy_fields(old_cp());
scratch_cp->copy_fields(old_cp());
log_info(redefine, class, constantpool)("merge_cp_len=%d, index_map_len=%d", merge_cp_length, _index_map_count);
@ -3373,9 +3372,7 @@ void VM_RedefineClasses::set_new_constant_pool(
// reference to the cp holder is needed for copy_operands()
smaller_cp->set_pool_holder(scratch_class);
if (scratch_cp->has_dynamic_constant()) {
smaller_cp->set_has_dynamic_constant();
}
smaller_cp->copy_fields(scratch_cp());
scratch_cp->copy_cp_to(1, scratch_cp_length - 1, smaller_cp, 1, THREAD);
if (HAS_PENDING_EXCEPTION) {
@ -4254,16 +4251,6 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
swap_annotations(the_class, scratch_class);
// Replace minor version number of class file
u2 old_minor_version = the_class->minor_version();
the_class->set_minor_version(scratch_class->minor_version());
scratch_class->set_minor_version(old_minor_version);
// Replace major version number of class file
u2 old_major_version = the_class->major_version();
the_class->set_major_version(scratch_class->major_version());
scratch_class->set_major_version(old_major_version);
// Replace CP indexes for class and name+type of enclosing method
u2 old_class_idx = the_class->enclosing_method_class_index();
u2 old_method_idx = the_class->enclosing_method_method_index();

@ -210,6 +210,10 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
nonstatic_field(ConstantPool, _operands, Array<u2>*) \
nonstatic_field(ConstantPool, _resolved_klasses, Array<Klass*>*) \
nonstatic_field(ConstantPool, _length, int) \
nonstatic_field(ConstantPool, _minor_version, u2) \
nonstatic_field(ConstantPool, _major_version, u2) \
nonstatic_field(ConstantPool, _generic_signature_index, u2) \
nonstatic_field(ConstantPool, _source_file_name_index, u2) \
nonstatic_field(ConstantPoolCache, _resolved_references, OopHandle) \
nonstatic_field(ConstantPoolCache, _reference_map, Array<u2>*) \
nonstatic_field(ConstantPoolCache, _length, int) \
@ -222,7 +226,6 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
nonstatic_field(InstanceKlass, _fields, Array<u2>*) \
nonstatic_field(InstanceKlass, _java_fields_count, u2) \
nonstatic_field(InstanceKlass, _constants, ConstantPool*) \
nonstatic_field(InstanceKlass, _source_file_name_index, u2) \
nonstatic_field(InstanceKlass, _source_debug_extension, const char*) \
nonstatic_field(InstanceKlass, _inner_classes, Array<jushort>*) \
nonstatic_field(InstanceKlass, _nonstatic_field_size, int) \
@ -230,9 +233,7 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
nonstatic_field(InstanceKlass, _static_oop_field_count, u2) \
nonstatic_field(InstanceKlass, _nonstatic_oop_map_size, int) \
nonstatic_field(InstanceKlass, _is_marked_dependent, bool) \
nonstatic_field(InstanceKlass, _misc_flags, u4) \
nonstatic_field(InstanceKlass, _minor_version, u2) \
nonstatic_field(InstanceKlass, _major_version, u2) \
nonstatic_field(InstanceKlass, _misc_flags, u2) \
nonstatic_field(InstanceKlass, _init_state, u1) \
nonstatic_field(InstanceKlass, _init_thread, Thread*) \
nonstatic_field(InstanceKlass, _itable_len, int) \
@ -241,7 +242,6 @@ typedef HashtableEntry<InstanceKlass*, mtClass> KlassHashtableEntry;
nonstatic_field(InstanceKlass, _jni_ids, JNIid*) \
nonstatic_field(InstanceKlass, _osr_nmethods_head, nmethod*) \
JVMTI_ONLY(nonstatic_field(InstanceKlass, _breakpoints, BreakpointInfo*)) \
nonstatic_field(InstanceKlass, _generic_signature_index, u2) \
volatile_nonstatic_field(InstanceKlass, _methods_jmethod_ids, jmethodID*) \
volatile_nonstatic_field(InstanceKlass, _idnum_allocated_count, u2) \
nonstatic_field(InstanceKlass, _annotations, Annotations*) \

@ -235,7 +235,11 @@ inline int wcslen(const jchar* x) { return wcslen((const wchar_t*)x); }
#define FORMAT64_MODIFIER "ll"
#endif // _LP64
#define offset_of(klass,field) offsetof(klass,field)
// gcc warns about applying offsetof() to non-POD object or calculating
// offset directly when base address is NULL. Use 16 to get around the
// warning. The -Wno-invalid-offsetof option could be used to suppress
// this warning, but we instead just avoid the use of offsetof().
#define offset_of(klass,field) (size_t)((intx)&(((klass*)16)->field) - 16)
#if defined(_LP64) && defined(__APPLE__)
#define JLONG_FORMAT "%ld"

@ -350,7 +350,7 @@ enum NamedGroup {
static NamedGroup nameOf(String name) {
for (NamedGroup group : NamedGroup.values()) {
if (group.name.equals(name)) {
if (group.name.equalsIgnoreCase(name)) {
return group;
}
}

@ -30,18 +30,18 @@ import java.util.HashMap;
import java.util.Map;
import com.sun.source.doctree.AttributeTree.ValueKind;
import com.sun.source.doctree.ErroneousTree;
import com.sun.source.doctree.UnknownBlockTagTree;
import com.sun.tools.javac.parser.DocCommentParser.TagParser.Kind;
import com.sun.tools.javac.parser.Tokens.Comment;
import com.sun.tools.javac.parser.Tokens.TokenKind;
import com.sun.tools.javac.tree.DCTree;
import com.sun.tools.javac.tree.DCTree.DCAttribute;
import com.sun.tools.javac.tree.DCTree.DCDocComment;
import com.sun.tools.javac.tree.DCTree.DCEndElement;
import com.sun.tools.javac.tree.DCTree.DCEndPosTree;
import com.sun.tools.javac.tree.DCTree.DCErroneous;
import com.sun.tools.javac.tree.DCTree.DCIdentifier;
import com.sun.tools.javac.tree.DCTree.DCReference;
import com.sun.tools.javac.tree.DCTree.DCStartElement;
import com.sun.tools.javac.tree.DCTree.DCText;
import com.sun.tools.javac.tree.DocTreeMaker;
import com.sun.tools.javac.tree.JCTree;
@ -54,7 +54,7 @@ import com.sun.tools.javac.util.Names;
import com.sun.tools.javac.util.Position;
import com.sun.tools.javac.util.StringUtils;
import static com.sun.tools.javac.util.LayoutCharacters.*;
import static com.sun.tools.javac.util.LayoutCharacters.EOI;
/**
*
@ -261,7 +261,7 @@ public class DocCommentParser {
/**
* Read a series of block tags, including their content.
* Standard tags parse their content appropriately.
* Non-standard tags are represented by {@link UnknownBlockTag}.
* Non-standard tags are represented by {@link UnknownBlockTagTree}.
*/
protected List<DCTree> blockTags() {
ListBuffer<DCTree> tags = new ListBuffer<>();
@ -273,7 +273,7 @@ public class DocCommentParser {
/**
* Read a single block tag, including its content.
* Standard tags parse their content appropriately.
* Non-standard tags are represented by {@link UnknownBlockTag}.
* Non-standard tags are represented by {@link UnknownBlockTagTree}.
*/
protected DCTree blockTag() {
int p = bp;
@ -321,8 +321,8 @@ public class DocCommentParser {
/**
* Read a single inline tag, including its content.
* Standard tags parse their content appropriately.
* Non-standard tags are represented by {@link UnknownBlockTag}.
* Malformed tags may be returned as {@link Erroneous}.
* Non-standard tags are represented by {@link UnknownBlockTagTree}.
* Malformed tags may be returned as {@link ErroneousTree}.
*/
protected DCTree inlineTag() {
int p = bp - 1;
@ -413,13 +413,6 @@ public class DocCommentParser {
lastNonWhite = bp;
break;
case '@':
if (newline)
break loop;
newline = false;
lastNonWhite = bp;
break;
default:
newline = false;
lastNonWhite = bp;

@ -92,6 +92,10 @@ public class ConstantPool extends Metadata implements ClassConstants {
poolHolder = new MetadataField(type.getAddressField("_pool_holder"), 0);
length = new CIntField(type.getCIntegerField("_length"), 0);
resolved_klasses = type.getAddressField("_resolved_klasses");
majorVersion = new CIntField(type.getCIntegerField("_major_version"), 0);
minorVersion = new CIntField(type.getCIntegerField("_minor_version"), 0);
sourceFileNameIndex = new CIntField(type.getCIntegerField("_source_file_name_index"), 0);
genericSignatureIndex = new CIntField(type.getCIntegerField("_generic_signature_index"), 0);
headerSize = type.getSize();
elementSize = 0;
// fetch constants:
@ -112,6 +116,10 @@ public class ConstantPool extends Metadata implements ClassConstants {
private static AddressField resolved_klasses;
private static MetadataField poolHolder;
private static CIntField length; // number of elements in oop
private static CIntField majorVersion;
private static CIntField minorVersion;
private static CIntField genericSignatureIndex;
private static CIntField sourceFileNameIndex;
private static long headerSize;
private static long elementSize;
@ -131,6 +139,20 @@ public class ConstantPool extends Metadata implements ClassConstants {
public Oop getResolvedReferences() {
return getCache().getResolvedReferences();
}
public long majorVersion() { return majorVersion.getValue(this); }
public long minorVersion() { return minorVersion.getValue(this); }
public Symbol getGenericSignature() {
long index = genericSignatureIndex.getValue(this);
if (index != 0) {
return getSymbolAt(index);
} else {
return null;
}
}
public Symbol getSourceFileName() { return getSymbolAt(sourceFileNameIndex.getValue(this)); }
public KlassArray getResolvedKlasses() {
return new KlassArray(resolved_klasses.getValue(getAddress()));
}

@ -95,7 +95,6 @@ public class InstanceKlass extends Klass {
constants = new MetadataField(type.getAddressField("_constants"), 0);
sourceDebugExtension = type.getAddressField("_source_debug_extension");
innerClasses = type.getAddressField("_inner_classes");
sourceFileNameIndex = new CIntField(type.getCIntegerField("_source_file_name_index"), 0);
nonstaticFieldSize = new CIntField(type.getCIntegerField("_nonstatic_field_size"), 0);
staticFieldSize = new CIntField(type.getCIntegerField("_static_field_size"), 0);
staticOopFieldCount = new CIntField(type.getCIntegerField("_static_oop_field_count"), 0);
@ -106,10 +105,7 @@ public class InstanceKlass extends Klass {
if (VM.getVM().isJvmtiSupported()) {
breakpoints = type.getAddressField("_breakpoints");
}
genericSignatureIndex = new CIntField(type.getCIntegerField("_generic_signature_index"), 0);
miscFlags = new CIntField(type.getCIntegerField("_misc_flags"), 0);
majorVersion = new CIntField(type.getCIntegerField("_major_version"), 0);
minorVersion = new CIntField(type.getCIntegerField("_minor_version"), 0);
headerSize = type.getSize();
// read field offset constants
@ -169,7 +165,6 @@ public class InstanceKlass extends Klass {
private static MetadataField constants;
private static AddressField sourceDebugExtension;
private static AddressField innerClasses;
private static CIntField sourceFileNameIndex;
private static CIntField nonstaticFieldSize;
private static CIntField staticFieldSize;
private static CIntField staticOopFieldCount;
@ -178,10 +173,7 @@ public class InstanceKlass extends Klass {
private static CIntField initState;
private static CIntField itableLen;
private static AddressField breakpoints;
private static CIntField genericSignatureIndex;
private static CIntField miscFlags;
private static CIntField majorVersion;
private static CIntField minorVersion;
// type safe enum for ClassState from instanceKlass.hpp
public static class ClassState {
@ -427,23 +419,16 @@ public class InstanceKlass extends Klass {
return allFieldsCount;
}
public ConstantPool getConstants() { return (ConstantPool) constants.getValue(this); }
public Symbol getSourceFileName() { return getConstants().getSymbolAt(sourceFileNameIndex.getValue(this)); }
public Symbol getSourceFileName() { return getConstants().getSourceFileName(); }
public String getSourceDebugExtension(){ return CStringUtilities.getString(sourceDebugExtension.getValue(getAddress())); }
public long getNonstaticFieldSize() { return nonstaticFieldSize.getValue(this); }
public long getStaticOopFieldCount() { return staticOopFieldCount.getValue(this); }
public long getNonstaticOopMapSize() { return nonstaticOopMapSize.getValue(this); }
public boolean getIsMarkedDependent() { return isMarkedDependent.getValue(this) != 0; }
public long getItableLen() { return itableLen.getValue(this); }
public long majorVersion() { return majorVersion.getValue(this); }
public long minorVersion() { return minorVersion.getValue(this); }
public Symbol getGenericSignature() {
long index = genericSignatureIndex.getValue(this);
if (index != 0) {
return getConstants().getSymbolAt(index);
} else {
return null;
}
}
public long majorVersion() { return getConstants().majorVersion(); }
public long minorVersion() { return getConstants().minorVersion(); }
public Symbol getGenericSignature() { return getConstants().getGenericSignature(); }
// "size helper" == instance size in words
public long getSizeHelper() {

@ -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.
*
* 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 {
private static final String LIBRARY_NAME = "libapplauncher.so";
final static String DEFAULT_ICON = "java32.png";
private final ApplicationLayout appLayout;
@ -109,11 +108,6 @@ public class LinuxAppImageBuilder extends AbstractAppImageBuilder {
// create the primary launcher
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
List<Map<String, ? super Object>> entryPoints
= StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,39 +23,36 @@
* questions.
*/
#ifndef PLATFORM_DEFS_H
#define PLATFORM_DEFS_H
#include "AppLauncher.h"
#include "FileUtils.h"
#include "UnixSysInfo.h"
// Define Windows compatibility requirements XP or later
#define WINVER 0x0600
#define _WIN32_WINNT 0x0600
#include <Windows.h>
#include <tchar.h>
#include <shlobj.h>
#include <direct.h>
#include <process.h>
#include <malloc.h>
#include <string>
namespace {
using namespace std;
void launchApp() {
setlocale(LC_ALL, "en_US.utf8");
#ifndef WINDOWS
#define WINDOWS
#endif
const tstring launcherPath = SysInfo::getProcessModulePath();
typedef std::wstring TString;
#define StringLength wcslen
// Launcher should be in "bin" subdirectory of app image.
const tstring appImageRoot = FileUtils::dirname(
FileUtils::dirname(launcherPath));
#define TRAILING_PATHSEPARATOR '\\'
#define BAD_TRAILING_PATHSEPARATOR '/'
#define PATH_SEPARATOR ';'
#define BAD_PATH_SEPARATOR ':'
AppLauncher()
.setImageRoot(appImageRoot)
.addJvmLibName(_T("lib/libjli.so"))
.setAppDir(FileUtils::mkpath() << appImageRoot << _T("lib/app"))
.setDefaultRuntimePath(FileUtils::mkpath() << appImageRoot
<< _T("lib/runtime"))
.launch();
}
typedef ULONGLONG TPlatformNumber;
typedef DWORD TProcessID;
} // namespace
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);
}

@ -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

@ -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;
}

@ -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

@ -65,7 +65,6 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
private static final ResourceBundle I18N = ResourceBundle.getBundle(
"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 OS_TYPE_CODE = "APPL";
private static final String TEMPLATE_INFO_PLIST_LITE =
@ -265,11 +264,9 @@ public class MacAppImageBuilder extends AbstractAppImageBuilder {
// create the main app launcher
try (InputStream is_launcher =
getResourceAsStream("jpackageapplauncher");
InputStream is_lib = getResourceAsStream(LIBRARY_NAME)) {
getResourceAsStream("jpackageapplauncher")) {
// Copy executable and library to MacOS folder
writeEntry(is_launcher, executable);
writeEntry(is_lib, macOSDir.resolve(LIBRARY_NAME));
}
executable.toFile().setExecutable(true, false);
// generate main app launcher config 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);
}

@ -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

@ -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;
}

@ -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

@ -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;
}

@ -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

@ -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.
*
* 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
// of the format com/foo/Main
if (mainJar != null) {
out.println("app.mainjar=" + getCfgAppDir()
out.println("app.classpath=" + getCfgAppDir()
+ mainJar.toPath().getFileName().toString());
}
if (mainClass != null) {
out.println("app.mainclass="
+ mainClass.replace("\\", "/"));
out.println("app.mainclass=" + mainClass);
}
}
@ -133,26 +132,20 @@ public abstract class AbstractAppImageBuilder {
out.println("[JavaOptions]");
List<String> jvmargs = JAVA_OPTIONS.fetchFrom(params);
for (String arg : jvmargs) {
out.println(arg);
out.println("java-options=" + arg);
}
Path modsDir = getAppModsDir();
if (modsDir != null && modsDir.toFile().exists()) {
out.println("--module-path");
out.println(getCfgAppDir().replace("\\","/") + "mods");
out.println("java-options=" + "--module-path");
out.println("java-options=" + getCfgAppDir().replace("\\","/") + "mods");
}
out.println();
out.println("[ArgOptions]");
List<String> args = ARGUMENTS.fetchFrom(params);
for (String arg : args) {
if (arg.endsWith("=") &&
(arg.indexOf("=") == arg.lastIndexOf("="))) {
out.print(arg.substring(0, arg.length() - 1));
out.println("\\=");
} else {
out.println(arg);
}
out.println("arguments=" + arg);
}
}
}

@ -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;
}

@ -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

@ -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

@ -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

@ -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");
}
}

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,37 +23,34 @@
* questions.
*/
#ifndef FILEATTRIBUTE_H
#define FILEATTRIBUTE_H
enum FileAttribute {
faBlockSpecial,
faCharacterSpecial,
faFIFOSpecial,
faNormal,
faDirectory,
faSymbolicLink,
faSocket,
#ifndef JvmLauncher_h
#define JvmLauncher_h
// Owner
faReadOnly,
faWriteOnly,
faReadWrite,
faExecute,
#include "tstrings.h"
// Group
faGroupReadOnly,
faGroupWriteOnly,
faGroupReadWrite,
faGroupExecute,
class CfgFile;
// 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

@ -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_

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,6 +24,8 @@
*/
#include <algorithm>
#include <string.h>
#include <cerrno>
#include "ErrorHandling.h"
#include "Log.h"
@ -47,7 +49,7 @@ void reportError(const SourceCodePos& pos, const tstring& msg) {
} // 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 \'"
<< 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;
printer << getFilename(pos) << "(" << pos.lno << ") at "
<< pos.func << "(): "
@ -139,3 +141,16 @@ std::string joinErrorMessages(const std::string& a, const std::string& b) {
}
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
}

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -50,18 +50,26 @@
// 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'.
// Assumed to be called from catch (...) {}
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 lastCRTError();
class JpErrorBase {
public:
virtual const char* rawMessage() const throw() = 0;
};
template <class Base>
class JpError: public Base {
class JpError: public JpErrorBase, public Base {
public:
JpError(const Base& e, const SourceCodePos& pos):
Base(e), msg(::makeMessage(e, pos)) {
@ -74,10 +82,15 @@ public:
const char* what() const throw() {
return msg.c_str();
}
// override JpErrorBase
const char* rawMessage() const throw() {
return Base::what();
}
private:
// Assert Base is derived from std::exception
// Assert Base is derived from std::runtime_error
enum { isDerivedFromStdException =
sizeof(static_cast<std::exception*>((Base*)0)) };
sizeof(static_cast<std::runtime_error*>((Base*)0)) };
std::string msg;
};
@ -129,7 +142,7 @@ inline JpError<std::runtime_error> makeException(
do {} while(0)
#define JP_CATCH_STD_EXCEPTION \
catch (const std::exception& e) \
catch (const std::runtime_error& e) \
{ \
JP_HANDLE_ERROR(e); \
}

@ -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

@ -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

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -24,7 +24,6 @@
*/
#include "Log.h"
#include "SysInfo.h"
#include "FileUtils.h"
@ -46,12 +45,10 @@ namespace {
// by default log everything
const Logger::LogLevel defaultLogLevel = Logger::LOG_TRACE;
char defaultLogAppenderMemory[sizeof(StderrLogAppender)] = {};
char defaultLogAppenderMemory[sizeof(StreamLogAppender)] = {};
char defaultLoggerMemory[sizeof(Logger)] = {};
NopLogAppender nopLogApender;
LPCTSTR getLogLevelStr(Logger::LogLevel level) {
switch (level) {
case Logger::LOG_TRACE:
@ -66,26 +63,12 @@ namespace {
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 };
State state = NotInitialized;
}
LogEvent::LogEvent() {
memset(this, 0, sizeof(*this));
moduleName = tstring();
logLevel = tstring();
fileName = tstring();
funcName = tstring();
@ -93,10 +76,6 @@ LogEvent::LogEvent() {
}
StderrLogAppender::StderrLogAppender() {
}
/*static*/
Logger& Logger::defaultLogger() {
Logger* reply = reinterpret_cast<Logger*>(defaultLoggerMemory);
@ -106,27 +85,17 @@ Logger& Logger::defaultLogger() {
// object. OS will do resources clean up anyways when application
// terminates and the default log appender should live as long as
// application lives.
reply->appender = new (defaultLogAppenderMemory) StderrLogAppender();
reply->appender = new (defaultLogAppenderMemory) StreamLogAppender(
std::cout);
}
if (Initializing == state) {
// Recursive call to Logger::defaultLogger.
moduleName[0] = TCHAR(0);
initializingLogging();
} else if (NotInitialized == state) {
state = Initializing;
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;
}
initializeLogging();
state = Initialized;
}
@ -152,14 +121,8 @@ bool Logger::isLoggable(LogLevel logLevel) const {
void Logger::log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
LPCTSTR funcName, const tstring& message) const {
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.funcName = funcName;
logEvent.logLevel = getLogLevelStr(logLevel);
@ -170,18 +133,20 @@ void Logger::log(LogLevel logLevel, LPCTSTR fileName, int lineNum,
}
void StderrLogAppender::append(const LogEvent& v)
{
const tstring out = tstrings::unsafe_format(format,
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());
void StreamLogAppender::append(const LogEvent& v) {
tstring platformLogStr;
LogEvent::appendFormatted(v, platformLogStr);
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;
}

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -26,7 +26,7 @@
#ifndef __LOG_H_INCLUDED_
#define __LOG_H_INCLUDED_
#include <windows.h>
#include "PlatformLogEvent.h"
#include "tstrings.h"
@ -45,11 +45,10 @@
* (usually value of the TMP env. var)
*/
struct LogEvent {
SYSTEMTIME ts;
long tid;
long pid;
tstring moduleName;
class Logger;
class StreamLogAppender;
struct LogEvent: public PlatformLogEvent {
tstring logLevel;
tstring fileName;
int lineNum;
@ -57,6 +56,14 @@ struct LogEvent {
tstring message;
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:
explicit StderrLogAppender();
explicit StreamLogAppender(std::ostream& consumer) : consumer(&consumer) {
}
virtual void append(const LogEvent& v);
private:
std::ostream* consumer;
};
@ -154,19 +166,42 @@ public:
private:
const Logger &log;
const LogLevel level;
const bool needLog;
const tstring file;
const int line;
const tstring func;
const tstring scope;
const bool needLog;
};
private:
static void initializingLogging();
static void initializeLogging();
private:
LogLevel level;
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
#define LOGGER_LOG(logger, logLevel, message) \
do { \

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -47,7 +47,11 @@ struct SourceCodePos
// Initializes SourceCodePos instance with the
// 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

@ -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

@ -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

@ -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.
*
* 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
ret = _vsntprintf_s(&*fmtout.begin(), fmtout.size(), _TRUNCATE, format, args);
#else
#ifdef __GNUC__
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wformat-nonliteral"
#endif
// With g++ this compiles only with '-std=gnu++0x' option
ret = vsnprintf(&*fmtout.begin(), fmtout.size(), format, args);
#ifdef __GNUC__
#pragma GCC diagnostic pop
#endif
#endif
} while(-1 == ret);
va_end(args);

@ -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.
*
* 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) {
return (v ? v : "(null)");
return std::string(v ? v: "(null)");
}
#ifdef TSTRINGS_WITH_WCHAR
@ -207,7 +207,7 @@ namespace format_detail {
}
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
void arg(const std::wstring&); // Compilation error by design.

@ -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

@ -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;
}

@ -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

@ -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();
}

@ -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

@ -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;
}

@ -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

@ -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;
}

@ -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

@ -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));
}

@ -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;
}

@ -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

@ -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

@ -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;
}

@ -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

@ -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;
}

@ -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

@ -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;
}

@ -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

@ -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

@ -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;
}

@ -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

@ -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() {
}
}

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,27 +23,22 @@
* questions.
*/
#ifndef MACROS_H
#define MACROS_H
#include "Platform.h"
#include <map>
#include "PlatformLogEvent.h"
#include "Log.h"
class Macros {
private:
std::map<TString, TString> FData;
void LogEvent::init(PlatformLogEvent& logEvent) {
}
Macros(void);
public:
static Macros& GetInstance();
static void Initialize();
~Macros(void);
void LogEvent::appendFormatted(const PlatformLogEvent& logEvent,
tstring& buffer) {
}
TString ExpandMacros(TString Value);
void AddMacro(TString Key, TString Value);
};
#endif // MACROS_H
void Logger::initializingLogging() {
}
void Logger::initializeLogging() {
}

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,13 +23,11 @@
* questions.
*/
#include <windows.h>
#ifndef PlatformLogEvent_h
#define PlatformLogEvent_h
extern "C" {
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
LPVOID lpvReserved) {
return true;
}
}
struct PlatformLogEvent {
};
#endif // PlatformLogEvent_h

@ -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);
}
}

@ -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.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,45 +23,43 @@
* questions.
*/
#ifndef PLATFORM_DEFS_H
#define PLATFORM_DEFS_H
#include <errno.h>
#include <unistd.h>
#include <limits.h>
#include <sys/stat.h>
#include <dlfcn.h>
#include <libgen.h>
#include <string>
#include <unistd.h>
#include "FileUtils.h"
#include "ErrorHandling.h"
using namespace std;
#ifndef LINUX
#define LINUX
#endif
namespace FileUtils {
#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 '/'
#define BAD_TRAILING_PATHSEPARATOR '\\'
#define PATH_SEPARATOR ':'
#define BAD_PATH_SEPARATOR ';'
#define MAX_PATH 1000
JP_THROW(tstrings::any() << "getcwd() failed. Error: "
<< lastCRTError());
}
typedef long TPlatformNumber;
typedef pid_t TProcessID;
if (isDirSeparator(path[0])) {
return path;
}
#define HMODULE void*
return mkpath() << toAbsolutePath("") << path;
}
typedef void* Module;
typedef void* Procedure;
#define StringToFileSystemString PlatformString
#define FileSystemStringToString PlatformString
#endif // PLATFORM_DEFS_H
} // namespace FileUtils

@ -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

@ -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

@ -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();
}
}
}

@ -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);
}

@ -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();
}

@ -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

@ -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.
*
* 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");
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";
@ -189,13 +187,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
// copy the jars
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
List<Map<String, ? super Object>> entryPoints =
StandardBundlerParam.ADD_LAUNCHERS.fetchFrom(params);
@ -209,27 +200,6 @@ public class WindowsAppImageBuilder extends AbstractAppImageBuilder {
public void prepareJreFiles(Map<String, ? super Object> params)
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(
Map<String, String> data, String key,
BundlerParamInfo<String> param,

@ -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

@ -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);
}

Some files were not shown because too many files have changed in this diff Show More