mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-02 04:00:16 +00:00
Merge
This commit is contained in:
commit
ce0c1fcc34
@ -34,28 +34,23 @@ include JavaCompilation.gmk
|
||||
include NativeCompilation.gmk
|
||||
include SetupJavaCompilers.gmk
|
||||
|
||||
# The exception handling of swing beaninfo which have the own tool directory
|
||||
ifeq (, $(BUILD_TOOLS_JDK))
|
||||
$(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
|
||||
SETUP := GENERATE_OLDBYTECODE, \
|
||||
ADD_JAVAC_FLAGS := "-Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes", \
|
||||
SRC := $(JDK_TOPDIR)/make/src/classes, \
|
||||
BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
|
||||
COPY := boot.modules ext.modules))
|
||||
endif
|
||||
################################################################################
|
||||
|
||||
$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources/%.template: \
|
||||
$(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/%.template
|
||||
$(call install-file)
|
||||
$(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
|
||||
SETUP := GENERATE_OLDBYTECODE, \
|
||||
ADD_JAVAC_FLAGS := "-Xbootclasspath/p:$(BUILDTOOLS_OUTPUTDIR)/interim_jimage_classes", \
|
||||
SRC := $(JDK_TOPDIR)/make/src/classes, \
|
||||
BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes, \
|
||||
COPY := boot.modules ext.modules))
|
||||
|
||||
BUILD_TOOLS_JDK += $(foreach i, $(wildcard $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/*.template), $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources/$(notdir $i))
|
||||
$(eval $(call SetupCopyFiles,COPY_NIMBUS_TEMPLATES, \
|
||||
SRC := $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus, \
|
||||
DEST := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/generatenimbus/resources, \
|
||||
FILES := $(wildcard $(JDK_TOPDIR)/src/java.desktop/share/classes/javax/swing/plaf/nimbus/*.template)))
|
||||
|
||||
# Resource used by CheckDeps tool
|
||||
$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/deps/refs.allowed: \
|
||||
$(JDK_TOPDIR)/make/data/checkdeps/refs.allowed
|
||||
$(call install-file)
|
||||
BUILD_TOOLS_JDK += $(COPY_NIMBUS_TEMPLATES)
|
||||
|
||||
BUILD_TOOLS_JDK += $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes/build/tools/deps/refs.allowed
|
||||
################################################################################
|
||||
|
||||
# Add a checksum ("jsum") to the end of a text file. Prevents trivial tampering with class lists.
|
||||
TOOL_ADDJSUM = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
@ -130,10 +125,6 @@ TOOL_OSX_TOBIN = $(JAVA_SMALL) -Djava.awt.headless=true -cp $(BUILDTOOLS_OUTPUTD
|
||||
TOOL_CLDRCONVERTER = $(JAVA_SMALL) -cp $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes \
|
||||
build.tools.cldrconverter.CLDRConverter
|
||||
|
||||
TOOL_CHECKDEPS = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \
|
||||
-cp "$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes$(PATH_SEP)$(JDK_OUTPUTDIR)" \
|
||||
build.tools.deps.CheckDeps
|
||||
|
||||
TOOL_GENMODULESXML = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \
|
||||
-cp "$(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes$(PATH_SEP)$(JDK_OUTPUTDIR)" \
|
||||
build.tools.module.GenJdepsModulesXml
|
||||
@ -161,25 +152,25 @@ $(eval $(call SetupJavaCompilation,BUILD_INTERIM_JIMAGE, \
|
||||
# Tools needed on solaris because OBJCOPY is broken.
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), solaris)
|
||||
$(eval $(call SetupNativeCompilation,ADD_GNU_DEBUGLINK, \
|
||||
SRC := $(JDK_TOPDIR)/make/src/native/add_gnu_debuglink, \
|
||||
LANG := C, \
|
||||
CC := $(BUILD_CC), \
|
||||
LDEXE := $(BUILD_LD), \
|
||||
LDFLAGS := -lelf, \
|
||||
OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/add_gnu_debuglink, \
|
||||
OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
|
||||
PROGRAM := add_gnu_debuglink))
|
||||
$(eval $(call SetupNativeCompilation,ADD_GNU_DEBUGLINK, \
|
||||
SRC := $(JDK_TOPDIR)/make/src/native/add_gnu_debuglink, \
|
||||
LANG := C, \
|
||||
CC := $(BUILD_CC), \
|
||||
LDEXE := $(BUILD_LD), \
|
||||
LDFLAGS := -lelf, \
|
||||
OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/add_gnu_debuglink, \
|
||||
OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
|
||||
PROGRAM := add_gnu_debuglink))
|
||||
|
||||
$(eval $(call SetupNativeCompilation,FIX_EMPTY_SEC_HDR_FLAGS, \
|
||||
SRC := $(JDK_TOPDIR)/make/src/native/fix_empty_sec_hdr_flags, \
|
||||
LANG := C, \
|
||||
CC := $(BUILD_CC), \
|
||||
LDEXE := $(BUILD_LD), \
|
||||
LDFLAGS := -lelf, \
|
||||
OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/fix_empty_sec_hdr_flags, \
|
||||
OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
|
||||
PROGRAM := fix_empty_sec_hdr_flags))
|
||||
$(eval $(call SetupNativeCompilation,FIX_EMPTY_SEC_HDR_FLAGS, \
|
||||
SRC := $(JDK_TOPDIR)/make/src/native/fix_empty_sec_hdr_flags, \
|
||||
LANG := C, \
|
||||
CC := $(BUILD_CC), \
|
||||
LDEXE := $(BUILD_LD), \
|
||||
LDFLAGS := -lelf, \
|
||||
OBJECT_DIR := $(BUILDTOOLS_OUTPUTDIR)/objs/fix_empty_sec_hdr_flags, \
|
||||
OUTPUT_DIR := $(BUILDTOOLS_OUTPUTDIR)/bin, \
|
||||
PROGRAM := fix_empty_sec_hdr_flags))
|
||||
endif
|
||||
|
||||
$(BUILD_TOOLS_JDK): $(BUILD_INTERIM_JIMAGE)
|
||||
|
||||
@ -1,34 +0,0 @@
|
||||
#
|
||||
# This properties-formatted file contains the names of the non-existent types
|
||||
# that are allowed to be referenced from classes in a profiles image.
|
||||
#
|
||||
# The property key is a type that does not exist. The property value is one or
|
||||
# more types that reference the missing type. The property value also encodes
|
||||
# the names of the profiles where this reference is allowed.
|
||||
|
||||
# jsse.jar is not subsetted by the profiles build. For compact1 and compact2
|
||||
# then this means that there are references to Kerberos types that do not
|
||||
# exist. These references are harmless.
|
||||
#
|
||||
javax.security.auth.kerberos.KerberosKey=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
|
||||
javax.security.auth.kerberos.KerberosPrincipal=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
|
||||
javax.security.auth.kerberos.KerberosTicket=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
javax.security.auth.kerberos.KeyTab=sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
|
||||
javax.security.auth.kerberos.ServicePermission=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
|
||||
sun.security.jgss.GSSCaller=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
|
||||
sun.security.jgss.krb5.Krb5Util=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,sun.security.ssl.krb5.Krb5ProxyImpl,compact1,compact2
|
||||
sun.security.jgss.krb5.ServiceCreds=sun.security.ssl.krb5.Krb5ProxyImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
sun.security.krb5.EncryptedData= sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
sun.security.krb5.EncryptionKey=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
sun.security.krb5.internal.crypto.KeyUsage=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
sun.security.krb5.internal.EncTicketPart=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
sun.security.krb5.internal.Krb5=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
sun.security.krb5.internal.Ticket=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
sun.security.krb5.KrbException=sun.security.ssl.krb5.KerberosPreMasterSecret,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
sun.security.krb5.PrincipalName=sun.security.ssl.krb5.Krb5ProxyImpl,sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
sun.security.krb5.Realm=sun.security.ssl.krb5.KerberosClientKeyExchangeImpl,compact1,compact2
|
||||
|
||||
# Residual references to java.beans.
|
||||
# The RemoveMethods tool does not yet purge the constant pool.
|
||||
#
|
||||
java.beans.PropertyChangeListener=java.util.logging.LogManager,compact1,compact2,compact3
|
||||
@ -28,6 +28,13 @@
|
||||
# string and the runtime name into the Version.java file.
|
||||
# To be printed by java -version
|
||||
|
||||
# These dependencies should ideally be added to prerequesites for Version.java
|
||||
# but skip for now until we have better incremental build for java.
|
||||
# $(call DependOnVariable, LAUNCHER_NAME) \
|
||||
# $(call DependOnVariable, RELEASE) \
|
||||
# $(call DependOnVariable, FULL_VERSION) \
|
||||
# $(call DependOnVariable, RUNTIME_VERSION)
|
||||
|
||||
$(SUPPORT_OUTPUTDIR)/gensrc/java.base/sun/misc/Version.java: \
|
||||
$(JDK_TOPDIR)/src/java.base/share/classes/sun/misc/Version.java.template
|
||||
$(MKDIR) -p $(@D)
|
||||
|
||||
@ -74,8 +74,6 @@ endif
|
||||
|
||||
##########################################################################################
|
||||
|
||||
BUILD_LIBVERIFY_SRC := check_code.c check_format.c
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), solaris)
|
||||
ifneq ($(OPENJDK_TARGET_CPU), x86_64)
|
||||
BUILD_LIBVERIFY_REORDER := $(JDK_TOPDIR)/make/mapfiles/libverify/reorder-$(OPENJDK_TARGET_CPU)
|
||||
@ -116,10 +114,6 @@ TARGETS += $(BUILD_LIBVERIFY)
|
||||
|
||||
LIBJAVA_SRC_DIRS := $(call FindSrcDirsForLib, java.base, java)
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||
LIBJAVA_EXCLUDE_FILES += $(JDK_TOPDIR)/src/java.base/unix/native/libjava/HostLocaleProviderAdapter_md.c
|
||||
endif
|
||||
|
||||
LIBJAVA_CFLAGS := $(addprefix -I, $(LIBJAVA_SRC_DIRS)) \
|
||||
-I$(JDK_TOPDIR)/src/java.base/share/native/libfdlibm \
|
||||
-I$(SUPPORT_OUTPUTDIR)/headers/java.base \
|
||||
@ -134,9 +128,7 @@ ifneq (, $(JDK_UPDATE_VERSION))
|
||||
LIBJAVA_CFLAGS += -DJDK_UPDATE_VERSION='"$(JDK_UPDATE_VERSION)"'
|
||||
endif
|
||||
|
||||
ifneq ($(OPENJDK_TARGET_OS), macosx)
|
||||
LIBJAVA_EXCLUDE_FILES += java_props_macosx.c
|
||||
else
|
||||
ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||
BUILD_LIBJAVA_java_props_md.c_CFLAGS := -x objective-c
|
||||
BUILD_LIBJAVA_java_props_macosx.c_CFLAGS := -x objective-c
|
||||
endif
|
||||
@ -151,8 +143,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAVA, \
|
||||
LIBRARY := java, \
|
||||
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
|
||||
SRC := $(LIBJAVA_SRC_DIRS), \
|
||||
EXCLUDES := fdlibm/src zip prefs, \
|
||||
EXCLUDE_FILES := $(LIBJAVA_EXCLUDE_FILES), \
|
||||
LANG := C, \
|
||||
OPTIMIZATION := HIGH, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) \
|
||||
@ -247,19 +237,10 @@ TARGETS += $(BUILD_LIBZIP)
|
||||
|
||||
##########################################################################################
|
||||
|
||||
BUILD_LIBJLI_SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/native/libjli \
|
||||
$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli
|
||||
LIBJLI_SRC_DIRS := $(call FindSrcDirsForLib, java.base, jli)
|
||||
|
||||
LIBJLI_CFLAGS := $(CFLAGS_JDKLIB)
|
||||
|
||||
BUILD_LIBJLI_FILES := \
|
||||
java.c \
|
||||
splashscreen_stubs.c \
|
||||
parse_manifest.c \
|
||||
version_comp.c \
|
||||
wildcard.c \
|
||||
jli_util.c
|
||||
|
||||
ifeq ($(JVM_VARIANT_ZERO), true)
|
||||
ERGO_FAMILY := zero
|
||||
else
|
||||
@ -269,68 +250,55 @@ else
|
||||
ERGO_FAMILY := $(OPENJDK_TARGET_CPU_ARCH)
|
||||
endif
|
||||
endif
|
||||
LIBJLI_ALL_ERGO := $(wildcard $(addsuffix /ergo_*.c, $(LIBJLI_SRC_DIRS)))
|
||||
LIBJLI_EXCLUDE_ERGO := $(filter-out %/ergo_$(ERGO_FAMILY).c, $(LIBJLI_ALL_ERGO))
|
||||
# If all specialized ergo files are excluded, use generic ergo
|
||||
ifeq ($(LIBJLI_ALL_ERGO), $(LIBJLI_EXCLUDE_ERGO))
|
||||
LIBJLI_CFLAGS += -DUSE_GENERIC_ERGO
|
||||
endif
|
||||
LIBJLI_EXCLUDE_FILES += $(notdir $(LIBJLI_EXCLUDE_ERGO))
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||
BUILD_LIBJLI_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/macosx/native/libjli
|
||||
BUILD_LIBJLI_FILES += java_md_common.c java_md_macosx.c
|
||||
LIBJLI_EXCLUDE_FILES += java_md_solinux.c ergo.c
|
||||
|
||||
BUILD_LIBJLI_java_md_macosx.c_CFLAGS := -x objective-c
|
||||
BUILD_LIBJLI_STATIC_java_md_macosx.c_CFLAGS := -x objective-c
|
||||
endif
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
BUILD_LIBJLI_FILES += java_md.c \
|
||||
cmdtoargs.c
|
||||
# Staticically link with c runtime on windows.
|
||||
LIBJLI_CFLAGS := $(filter-out -MD, $(LIBJLI_CFLAGS))
|
||||
else ifneq ($(OPENJDK_TARGET_OS), macosx)
|
||||
|
||||
BUILD_LIBJLI_FILES += java_md_common.c
|
||||
BUILD_LIBJLI_FILES += java_md_solinux.c ergo.c
|
||||
|
||||
ERGO_ARCH_FILE = ergo_$(ERGO_FAMILY).c
|
||||
|
||||
# if the architecture specific ergo file exists then
|
||||
# use it, else use the generic definitions from ergo.c
|
||||
ifneq ($(wildcard $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libjli/$(ERGO_ARCH_FILE)), )
|
||||
BUILD_LIBJLI_FILES += $(ERGO_ARCH_FILE)
|
||||
else # !ERGO_ARCH_FILE
|
||||
LIBJLI_CFLAGS += -DUSE_GENERIC_ERGO
|
||||
endif # ERGO_ARCH_FILE
|
||||
endif #WINDOWS
|
||||
|
||||
LIBJLI_CFLAGS += $(foreach dir, $(BUILD_LIBJLI_SRC_DIRS), -I$(dir))
|
||||
|
||||
# Append defines depending on target platform
|
||||
LIBJLI_CFLAGS += $(OPENJDK_TARGET_CPU_JLI_CFLAGS)
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||
LIBJLI_CFLAGS += -DPACKAGE_PATH=\"$(PACKAGE_PATH)\"
|
||||
endif
|
||||
|
||||
ifneq ($(USE_EXTERNAL_LIBZ), true)
|
||||
BUILD_LIBJLI_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/share/native/libzip/zlib-1.2.8
|
||||
LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS)
|
||||
BUILD_LIBJLI_FILES += \
|
||||
inflate.c \
|
||||
inftrees.c \
|
||||
inffast.c \
|
||||
zadler32.c \
|
||||
zcrc32.c \
|
||||
zutil.c
|
||||
endif
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
# Staticically link with c runtime on windows.
|
||||
LIBJLI_CFLAGS := $(filter-out -MD, $(LIBJLI_CFLAGS))
|
||||
LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)
|
||||
else
|
||||
LIBJLI_OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE)/jli
|
||||
endif
|
||||
|
||||
LIBJLI_CFLAGS += $(addprefix -I, $(LIBJLI_SRC_DIRS))
|
||||
|
||||
# Append defines depending on target platform
|
||||
LIBJLI_CFLAGS += $(OPENJDK_TARGET_CPU_JLI_CFLAGS)
|
||||
|
||||
ifneq ($(USE_EXTERNAL_LIBZ), true)
|
||||
LIBJLI_CFLAGS += $(ZLIB_CPPFLAGS)
|
||||
LIBJLI_EXTRA_FILES += \
|
||||
$(addprefix $(JDK_TOPDIR)/src/java.base/share/native/libzip/zlib-1.2.8/, \
|
||||
inflate.c \
|
||||
inftrees.c \
|
||||
inffast.c \
|
||||
zadler32.c \
|
||||
zcrc32.c \
|
||||
zutil.c \
|
||||
)
|
||||
endif
|
||||
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI, \
|
||||
LIBRARY := jli, \
|
||||
OUTPUT_DIR := $(LIBJLI_OUTPUT_DIR), \
|
||||
SRC := $(BUILD_LIBJLI_SRC_DIRS), \
|
||||
INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
|
||||
SRC := $(LIBJLI_SRC_DIRS), \
|
||||
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
|
||||
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
|
||||
LANG := C, \
|
||||
OPTIMIZATION := HIGH, \
|
||||
CFLAGS := $(LIBJLI_CFLAGS), \
|
||||
@ -376,8 +344,9 @@ ifeq ($(OPENJDK_TARGET_OS), windows)
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
|
||||
STATIC_LIBRARY := jli_static, \
|
||||
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
|
||||
SRC := $(BUILD_LIBJLI_SRC_DIRS), \
|
||||
INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
|
||||
SRC := $(LIBJLI_SRC_DIRS), \
|
||||
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
|
||||
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
|
||||
LANG := C, \
|
||||
OPTIMIZATION := HIGH, \
|
||||
CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \
|
||||
@ -395,8 +364,9 @@ else ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
|
||||
LIBRARY := jli_static, \
|
||||
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
|
||||
SRC := $(BUILD_LIBJLI_SRC_DIRS), \
|
||||
INCLUDE_FILES := $(BUILD_LIBJLI_FILES), \
|
||||
SRC := $(LIBJLI_SRC_DIRS), \
|
||||
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
|
||||
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
|
||||
LANG := C, \
|
||||
OPTIMIZATION := HIGH, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) $(LIBJLI_CFLAGS), \
|
||||
@ -411,16 +381,17 @@ else ifeq ($(OPENJDK_TARGET_OS), macosx)
|
||||
|
||||
else ifeq ($(OPENJDK_TARGET_OS), aix)
|
||||
# AIX also requires a static libjli because the compiler doesn't support '-rpath'
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC,\
|
||||
STATIC_LIBRARY:=jli_static,\
|
||||
OUTPUT_DIR:=$(SUPPORT_OUTPUTDIR)/native/$(MODULE),\
|
||||
SRC:=$(BUILD_LIBJLI_SRC_DIRS),\
|
||||
INCLUDE_FILES:=$(BUILD_LIBJLI_FILES),\
|
||||
LANG:=C,\
|
||||
OPTIMIZATION:=HIGH, \
|
||||
CFLAGS:=$(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS),\
|
||||
ARFLAGS:=$(ARFLAGS),\
|
||||
OBJECT_DIR:=$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static))
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBJLI_STATIC, \
|
||||
STATIC_LIBRARY := jli_static, \
|
||||
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE), \
|
||||
SRC := $(LIBJLI_SRC_DIRS), \
|
||||
EXCLUDE_FILES := $(LIBJLI_EXCLUDE_FILES), \
|
||||
EXTRA_FILES := $(LIBJLI_EXTRA_FILES), \
|
||||
LANG := C, \
|
||||
OPTIMIZATION := HIGH, \
|
||||
CFLAGS := $(STATIC_LIBRARY_FLAGS) $(LIBJLI_CFLAGS), \
|
||||
ARFLAGS := $(ARFLAGS), \
|
||||
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libjli_static))
|
||||
|
||||
TARGETS += $(BUILD_LIBJLI_STATIC)
|
||||
|
||||
|
||||
@ -31,7 +31,7 @@ include LibCommon.gmk
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBATTACH, \
|
||||
LIBRARY := attach, \
|
||||
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
|
||||
SRC := $(JDK_TOPDIR)/src/jdk.attach/$(OPENJDK_TARGET_OS)/native/libattach, \
|
||||
SRC := $(call FindSrcDirsForLib, jdk.attach, attach), \
|
||||
LANG := C, \
|
||||
OPTIMIZATION := LOW, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
|
||||
|
||||
@ -28,9 +28,7 @@ include LibCommon.gmk
|
||||
################################################################################
|
||||
|
||||
LIBJAAS_MAPFILE :=
|
||||
ifneq ($(OPENJDK_TARGET_OS), solaris)
|
||||
LIBJAAS_EXCLUDE_FILES := Solaris.c
|
||||
else
|
||||
ifeq ($(OPENJDK_TARGET_OS), solaris)
|
||||
# only on solaris...wonder why
|
||||
LIBJAAS_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjaas/mapfile-vers
|
||||
endif
|
||||
@ -43,7 +41,7 @@ endif
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBJAAS, \
|
||||
LIBRARY := $(LIBJAAS_NAME), \
|
||||
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
|
||||
SRC := $(JDK_TOPDIR)/src/jdk.security.auth/$(OPENJDK_TARGET_OS_TYPE)/native/libjaas, \
|
||||
SRC := $(call FindSrcDirsForLib, jdk.security.auth, jaas), \
|
||||
LANG := C, \
|
||||
OPTIMIZATION := LOW, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/jdk.security.auth, \
|
||||
@ -53,7 +51,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBJAAS, \
|
||||
LDFLAGS_windows := netapi32.lib user32.lib mpr.lib advapi32.lib, \
|
||||
LDFLAGS_SUFFIX_windows := $(LDFLAGS_JDKLIB_SUFFIX), \
|
||||
LDFLAGS_SUFFIX_solaris := -lc, \
|
||||
EXCLUDE_FILES := $(LIBJAAS_EXCLUDE_FILES), \
|
||||
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
|
||||
RC_FLAGS := $(RC_FLAGS) \
|
||||
-D "JDK_FNAME=$(LIBJAAS_NAME).dll" \
|
||||
|
||||
@ -23,39 +23,16 @@
|
||||
# questions.
|
||||
#
|
||||
|
||||
LIBNET_SRC_DIRS := $(JDK_TOPDIR)/src/java.base/share/native/libnet \
|
||||
$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_TYPE)/native/libnet
|
||||
LIBNET_CFLAGS += -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
|
||||
$(LIBJAVA_HEADER_FLAGS)
|
||||
|
||||
LIBNET_CFLAGS += $(foreach dir, $(LIBNET_SRC_DIRS), -I$(dir))
|
||||
|
||||
LIBNET_EXCLUDE_FILES :=
|
||||
ifneq ($(OPENJDK_TARGET_OS), solaris)
|
||||
LIBNET_EXCLUDE_FILES += solaris_close.c
|
||||
endif
|
||||
|
||||
ifneq ($(OPENJDK_TARGET_OS), linux)
|
||||
LIBNET_EXCLUDE_FILES += linux_close.c
|
||||
endif
|
||||
|
||||
ifneq ($(OPENJDK_TARGET_OS), macosx)
|
||||
LIBNET_EXCLUDE_FILES += bsd_close.c
|
||||
endif
|
||||
|
||||
ifeq ($(OPENJDK_TARGET_OS), aix)
|
||||
LIBNET_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libnet/java/net/
|
||||
endif
|
||||
LIBNET_SRC_DIRS := $(call FindSrcDirsForLib, java.base, net)
|
||||
|
||||
$(eval $(call SetupNativeCompilation,BUILD_LIBNET, \
|
||||
LIBRARY := net, \
|
||||
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
|
||||
SRC := $(LIBNET_SRC_DIRS), \
|
||||
EXCLUDE_FILES := $(LIBNET_EXCLUDE_FILES), \
|
||||
LANG := C, \
|
||||
OPTIMIZATION := LOW, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) \
|
||||
$(LIBNET_CFLAGS), \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) -I$(SUPPORT_OUTPUTDIR)/headers/java.base \
|
||||
$(LIBJAVA_HEADER_FLAGS) $(addprefix -I, $(LIBNET_SRC_DIRS)), \
|
||||
MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libnet/mapfile-vers, \
|
||||
LDFLAGS := $(LDFLAGS_JDKLIB) \
|
||||
$(call SET_SHARED_LIBRARY_ORIGIN), \
|
||||
|
||||
@ -65,7 +65,6 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBNIO, \
|
||||
OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
|
||||
SRC := $(BUILD_LIBNIO_SRC), \
|
||||
EXCLUDE_FILES := $(BUILD_LIBNIO_EXFILES), \
|
||||
EXCLUDES := sctp, \
|
||||
LANG := C, \
|
||||
OPTIMIZATION := HIGH, \
|
||||
CFLAGS := $(CFLAGS_JDKLIB) \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
#
|
||||
# Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
# Copyright (c) 1997, 2015, 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
|
||||
@ -214,10 +214,10 @@ SUNWprivate_1.1 {
|
||||
Java_java_lang_Throwable_fillInStackTrace;
|
||||
Java_java_lang_Throwable_getStackTraceDepth;
|
||||
Java_java_lang_Throwable_getStackTraceElement;
|
||||
Java_java_lang_UNIXProcess_init;
|
||||
Java_java_lang_UNIXProcess_waitForProcessExit;
|
||||
Java_java_lang_UNIXProcess_forkAndExec;
|
||||
Java_java_lang_UNIXProcess_destroyProcess;
|
||||
Java_java_lang_ProcessImpl_init;
|
||||
Java_java_lang_ProcessImpl_waitForProcessExit;
|
||||
Java_java_lang_ProcessImpl_forkAndExec;
|
||||
Java_java_lang_ProcessImpl_destroyProcess;
|
||||
Java_java_nio_Bits_copyFromShortArray;
|
||||
Java_java_nio_Bits_copyToShortArray;
|
||||
Java_java_nio_Bits_copyFromIntArray;
|
||||
|
||||
@ -1,226 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 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.
|
||||
*/
|
||||
|
||||
package build.tools.deps;
|
||||
|
||||
import java.nio.file.DirectoryStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.HashMap;
|
||||
import java.util.Enumeration;
|
||||
import java.util.Properties;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.net.URL;
|
||||
|
||||
import com.sun.tools.classfile.ClassFile;
|
||||
import com.sun.tools.classfile.Dependencies;
|
||||
import com.sun.tools.classfile.Dependency;
|
||||
|
||||
/**
|
||||
* A simple tool to check the JAR files in a JRE image to ensure that there
|
||||
* aren't any references to types that do not exist. The tool is intended to
|
||||
* be used in the JDK "profiles" build to help ensure that the profile
|
||||
* definitions are kept up to date.
|
||||
*/
|
||||
|
||||
public class CheckDeps {
|
||||
|
||||
// classfile API for finding dependencies
|
||||
static final Dependency.Finder finder = Dependencies.getClassDependencyFinder();
|
||||
|
||||
// "known types", found in rt.jar or other JAR files
|
||||
static final Set<String> knownTypes = new HashSet<>();
|
||||
|
||||
// References to unknown types. The map key is the unknown type, the
|
||||
// map value is the set of classes that reference it.
|
||||
static final Map<String,Set<String>> unknownRefs = new HashMap<>();
|
||||
|
||||
// The property name is the name of an unknown type that is allowed to be
|
||||
// references. The property value is a comma separated list of the types
|
||||
// that are allowed to reference it. The list also includes the names of
|
||||
// the profiles that the reference is allowed.
|
||||
static final Properties allowedBadRefs = new Properties();
|
||||
|
||||
/**
|
||||
* Returns the class name for the given class file. In the case of inner
|
||||
* classes then the enclosing class is returned in order to keep the
|
||||
* rules simple.
|
||||
*/
|
||||
static String toClassName(String s) {
|
||||
int i = s.indexOf('$');
|
||||
if (i > 0)
|
||||
s = s.substring(0, i);
|
||||
return s.replace("/", ".");
|
||||
}
|
||||
|
||||
/**
|
||||
* Analyze the dependencies of all classes in the given JAR file. The
|
||||
* method updates knownTypes and unknownRefs as part of the analysis.
|
||||
*/
|
||||
static void analyzeDependencies(Path jarpath) throws Exception {
|
||||
System.out.format("Analyzing %s%n", jarpath);
|
||||
try (JarFile jf = new JarFile(jarpath.toFile())) {
|
||||
Enumeration<JarEntry> entries = jf.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry e = entries.nextElement();
|
||||
String name = e.getName();
|
||||
if (name.endsWith(".class")) {
|
||||
ClassFile cf = ClassFile.read(jf.getInputStream(e));
|
||||
for (Dependency d : finder.findDependencies(cf)) {
|
||||
String origin = toClassName(d.getOrigin().getName());
|
||||
String target = toClassName(d.getTarget().getName());
|
||||
|
||||
// origin is now known
|
||||
unknownRefs.remove(origin);
|
||||
knownTypes.add(origin);
|
||||
|
||||
// if the target is not known then record the reference
|
||||
if (!knownTypes.contains(target)) {
|
||||
Set<String> refs = unknownRefs.get(target);
|
||||
if (refs == null) {
|
||||
// first time seeing this unknown type
|
||||
refs = new HashSet<>();
|
||||
unknownRefs.put(target, refs);
|
||||
}
|
||||
refs.add(origin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* We have closure (no references to types that do not exist) if
|
||||
* unknownRefs is empty. When unknownRefs is not empty then it should
|
||||
* only contain references that are allowed to be present (these are
|
||||
* loaded from the refs.allowed properties file).
|
||||
*
|
||||
* @param the profile that is being tested, this determines the exceptions
|
||||
* in {@code allowedBadRefs} that apply.
|
||||
*
|
||||
* @return {@code true} if there are no missing types or the only references
|
||||
* to missing types are described by {@code allowedBadRefs}.
|
||||
*/
|
||||
static boolean checkClosure(String profile) {
|
||||
// process the references to types that do not exist.
|
||||
boolean fail = false;
|
||||
for (Map.Entry<String,Set<String>> entry: unknownRefs.entrySet()) {
|
||||
String target = entry.getKey();
|
||||
for (String origin: entry.getValue()) {
|
||||
// check if origin -> target allowed
|
||||
String value = allowedBadRefs.getProperty(target);
|
||||
if (value == null) {
|
||||
System.err.format("%s -> %s (unknown type)%n", origin, target);
|
||||
fail = true;
|
||||
} else {
|
||||
// target is known, check if the origin is one that we
|
||||
// expect and that the exception applies to the profile.
|
||||
boolean found = false;
|
||||
boolean applicable = false;
|
||||
for (String s: value.split(",")) {
|
||||
s = s.trim();
|
||||
if (s.equals(origin))
|
||||
found = true;
|
||||
if (s.equals(profile))
|
||||
applicable = true;
|
||||
}
|
||||
if (!found || !applicable) {
|
||||
if (!found) {
|
||||
System.err.format("%s -> %s (not allowed)%n", origin, target);
|
||||
} else {
|
||||
System.err.format("%s -> %s (reference not applicable to %s)%n",
|
||||
origin, target, profile);
|
||||
}
|
||||
fail = true;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return !fail;
|
||||
}
|
||||
|
||||
static void fail(URL url) throws Exception {
|
||||
System.err.println("One or more unexpected references encountered");
|
||||
if (url != null)
|
||||
System.err.format("Check %s is up to date%n", Paths.get(url.toURI()));
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
// load properties file so that we know what missing types that are
|
||||
// allowed to be referenced.
|
||||
URL url = CheckDeps.class.getResource("refs.allowed");
|
||||
if (url != null) {
|
||||
try (InputStream in = url.openStream()) {
|
||||
allowedBadRefs.load(new InputStreamReader(in, StandardCharsets.UTF_8));
|
||||
}
|
||||
}
|
||||
|
||||
if (args.length != 2) {
|
||||
System.err.println("Usage: java CheckDeps <image> <profile>");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
String image = args[0];
|
||||
String profile = args[1];
|
||||
|
||||
// process JAR files on boot class path
|
||||
Path lib = Paths.get(image, "lib");
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(lib, "*.jar")) {
|
||||
for (Path jarpath: stream) {
|
||||
analyzeDependencies(jarpath);
|
||||
}
|
||||
}
|
||||
|
||||
// classes on boot class path should not reference other types
|
||||
boolean okay = checkClosure(profile);
|
||||
if (!okay)
|
||||
fail(url);
|
||||
|
||||
// process JAR files in the extensions directory
|
||||
try (DirectoryStream<Path> stream = Files.newDirectoryStream(lib.resolve("ext"), "*.jar")) {
|
||||
for (Path jarpath: stream) {
|
||||
analyzeDependencies(jarpath);
|
||||
}
|
||||
}
|
||||
|
||||
// re-check to ensure that the extensions doesn't reference types that
|
||||
// do not exist.
|
||||
okay = checkClosure(profile);
|
||||
if (!okay)
|
||||
fail(url);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2015, 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,6 +27,9 @@ package java.lang;
|
||||
|
||||
import sun.misc.FloatingDecimal;
|
||||
import java.util.Arrays;
|
||||
import java.util.Spliterator;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* A mutable sequence of characters.
|
||||
@ -292,7 +295,7 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
if (beginIndex < 0 || endIndex > count || beginIndex > endIndex) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
return Character.codePointCountImpl(value, beginIndex, endIndex-beginIndex);
|
||||
return Character.codePointCountImpl(value, beginIndex, endIndex - beginIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1431,6 +1434,34 @@ abstract class AbstractStringBuilder implements Appendable, CharSequence {
|
||||
@Override
|
||||
public abstract String toString();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.9
|
||||
*/
|
||||
@Override
|
||||
public IntStream chars() {
|
||||
// Reuse String-based spliterator. This requires a supplier to
|
||||
// capture the value and count when the terminal operation is executed
|
||||
return StreamSupport.intStream(
|
||||
() -> new String.IntCharArraySpliterator(value, 0, count, 0),
|
||||
Spliterator.ORDERED | Spliterator.SIZED | Spliterator.SUBSIZED,
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @since 1.9
|
||||
*/
|
||||
@Override
|
||||
public IntStream codePoints() {
|
||||
// Reuse String-based spliterator. This requires a supplier to
|
||||
// capture the value and count when the terminal operation is executed
|
||||
return StreamSupport.intStream(
|
||||
() -> new String.CodePointsSpliterator(value, 0, count, 0),
|
||||
Spliterator.ORDERED,
|
||||
false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed by {@code String} for the contentEquals method.
|
||||
*/
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2015, 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
|
||||
@ -86,12 +86,11 @@ public class Object {
|
||||
* for unequal objects may improve the performance of hash tables.
|
||||
* </ul>
|
||||
* <p>
|
||||
* As much as is reasonably practical, the hashCode method defined by
|
||||
* class {@code Object} does return distinct integers for distinct
|
||||
* objects. (This is typically implemented by converting the internal
|
||||
* address of the object into an integer, but this implementation
|
||||
* technique is not required by the
|
||||
* Java™ programming language.)
|
||||
* As much as is reasonably practical, the hashCode method defined
|
||||
* by class {@code Object} does return distinct integers for
|
||||
* distinct objects. (The hashCode may or may not be implemented
|
||||
* as some function of an object's memory address at some point
|
||||
* in time.)
|
||||
*
|
||||
* @return a hash code value for this object.
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
@ -344,10 +343,12 @@ public class Object {
|
||||
* ... // Perform action appropriate to condition
|
||||
* }
|
||||
* </pre>
|
||||
* (For more information on this topic, see Section 3.2.3 in Doug Lea's
|
||||
* "Concurrent Programming in Java (Second Edition)" (Addison-Wesley,
|
||||
* 2000), or Item 50 in Joshua Bloch's "Effective Java Programming
|
||||
* Language Guide" (Addison-Wesley, 2001).
|
||||
*
|
||||
* (For more information on this topic, see section 14.2,
|
||||
* Condition Queues, in Brian Goetz and others' "Java Concurrency
|
||||
* in Practice" (Addison-Wesley, 2006) or Item 69 in Joshua
|
||||
* Bloch's "Effective Java (Second Edition)" (Addison-Wesley,
|
||||
* 2008).
|
||||
*
|
||||
* <p>If the current thread is {@linkplain java.lang.Thread#interrupt()
|
||||
* interrupted} by any thread before or while it is waiting, then an
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1994, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1994, 2015, 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
|
||||
@ -34,10 +34,14 @@ import java.util.Comparator;
|
||||
import java.util.Formatter;
|
||||
import java.util.Locale;
|
||||
import java.util.Objects;
|
||||
import java.util.Spliterator;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.regex.PatternSyntaxException;
|
||||
import java.util.stream.IntStream;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
/**
|
||||
* The {@code String} class represents character strings. All
|
||||
@ -2894,6 +2898,180 @@ public final class String
|
||||
return this;
|
||||
}
|
||||
|
||||
static class IntCharArraySpliterator implements Spliterator.OfInt {
|
||||
private final char[] array;
|
||||
private int index; // current index, modified on advance/split
|
||||
private final int fence; // one past last index
|
||||
private final int cs;
|
||||
|
||||
IntCharArraySpliterator(char[] array, int acs) {
|
||||
this(array, 0, array.length, acs);
|
||||
}
|
||||
|
||||
IntCharArraySpliterator(char[] array, int origin, int fence, int acs) {
|
||||
this.array = array;
|
||||
this.index = origin;
|
||||
this.fence = fence;
|
||||
this.cs = acs | Spliterator.ORDERED | Spliterator.SIZED
|
||||
| Spliterator.SUBSIZED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfInt trySplit() {
|
||||
int lo = index, mid = (lo + fence) >>> 1;
|
||||
return (lo >= mid)
|
||||
? null
|
||||
: new IntCharArraySpliterator(array, lo, index = mid, cs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(IntConsumer action) {
|
||||
char[] a; int i, hi; // hoist accesses and checks from loop
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
if ((a = array).length >= (hi = fence) &&
|
||||
(i = index) >= 0 && i < (index = hi)) {
|
||||
do { action.accept(a[i]); } while (++i < hi);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(IntConsumer action) {
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
if (index >= 0 && index < fence) {
|
||||
action.accept(array[index++]);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() { return (long)(fence - index); }
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stream of {@code int} zero-extending the {@code char} values
|
||||
* from this sequence. Any char which maps to a <a
|
||||
* href="{@docRoot}/java/lang/Character.html#unicode">surrogate code
|
||||
* point</a> is passed through uninterpreted.
|
||||
*
|
||||
* @return an IntStream of char values from this sequence
|
||||
* @since 1.9
|
||||
*/
|
||||
@Override
|
||||
public IntStream chars() {
|
||||
return StreamSupport.intStream(
|
||||
new IntCharArraySpliterator(value, Spliterator.IMMUTABLE), false);
|
||||
}
|
||||
|
||||
static class CodePointsSpliterator implements Spliterator.OfInt {
|
||||
private final char[] array;
|
||||
private int index; // current index, modified on advance/split
|
||||
private final int fence; // one past last index
|
||||
private final int cs;
|
||||
|
||||
CodePointsSpliterator(char[] array, int acs) {
|
||||
this(array, 0, array.length, acs);
|
||||
}
|
||||
|
||||
CodePointsSpliterator(char[] array, int origin, int fence, int acs) {
|
||||
this.array = array;
|
||||
this.index = origin;
|
||||
this.fence = fence;
|
||||
this.cs = acs | Spliterator.ORDERED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public OfInt trySplit() {
|
||||
int lo = index, mid = (lo + fence) >>> 1;
|
||||
if (lo >= mid)
|
||||
return null;
|
||||
|
||||
int midOneLess;
|
||||
// If the mid-point intersects a surrogate pair
|
||||
if (Character.isLowSurrogate(array[mid]) &&
|
||||
Character.isHighSurrogate(array[midOneLess = (mid -1)])) {
|
||||
// If there is only one pair it cannot be split
|
||||
if (lo >= midOneLess)
|
||||
return null;
|
||||
// Shift the mid-point to align with the surrogate pair
|
||||
return new CodePointsSpliterator(array, lo, index = midOneLess, cs);
|
||||
}
|
||||
return new CodePointsSpliterator(array, lo, index = mid, cs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forEachRemaining(IntConsumer action) {
|
||||
char[] a; int i, hi; // hoist accesses and checks from loop
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
if ((a = array).length >= (hi = fence) &&
|
||||
(i = index) >= 0 && i < (index = hi)) {
|
||||
do {
|
||||
i = advance(a, i, hi, action);
|
||||
} while (i < hi);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean tryAdvance(IntConsumer action) {
|
||||
if (action == null)
|
||||
throw new NullPointerException();
|
||||
if (index >= 0 && index < fence) {
|
||||
index = advance(array, index, fence, action);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// Advance one code point from the index, i, and return the next
|
||||
// index to advance from
|
||||
private static int advance(char[] a, int i, int hi, IntConsumer action) {
|
||||
char c1 = a[i++];
|
||||
int cp = c1;
|
||||
if (Character.isHighSurrogate(c1) && i < hi) {
|
||||
char c2 = a[i];
|
||||
if (Character.isLowSurrogate(c2)) {
|
||||
i++;
|
||||
cp = Character.toCodePoint(c1, c2);
|
||||
}
|
||||
}
|
||||
action.accept(cp);
|
||||
return i;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long estimateSize() { return (long)(fence - index); }
|
||||
|
||||
@Override
|
||||
public int characteristics() {
|
||||
return cs;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a stream of code point values from this sequence. Any surrogate
|
||||
* pairs encountered in the sequence are combined as if by {@linkplain
|
||||
* Character#toCodePoint Character.toCodePoint} and the result is passed
|
||||
* to the stream. Any other code units, including ordinary BMP characters,
|
||||
* unpaired surrogates, and undefined code units, are zero-extended to
|
||||
* {@code int} values which are then passed to the stream.
|
||||
*
|
||||
* @return an IntStream of Unicode code points from this sequence
|
||||
* @since 1.9
|
||||
*/
|
||||
@Override
|
||||
public IntStream codePoints() {
|
||||
return StreamSupport.intStream(
|
||||
new CodePointsSpliterator(value, Spliterator.IMMUTABLE), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts this string to a new character array.
|
||||
*
|
||||
|
||||
@ -376,19 +376,16 @@ public final class System {
|
||||
* the difference between two such values, obtained within the same
|
||||
* instance of a Java virtual machine, is computed.
|
||||
*
|
||||
* <p> For example, to measure how long some code takes to execute:
|
||||
* <pre> {@code
|
||||
* <p>For example, to measure how long some code takes to execute:
|
||||
* <pre> {@code
|
||||
* long startTime = System.nanoTime();
|
||||
* // ... the code being measured ...
|
||||
* long estimatedTime = System.nanoTime() - startTime;}</pre>
|
||||
* long elapsedNanos = System.nanoTime() - startTime;}</pre>
|
||||
*
|
||||
* <p>To compare two nanoTime values
|
||||
* <pre> {@code
|
||||
* long t0 = System.nanoTime();
|
||||
* ...
|
||||
* long t1 = System.nanoTime();}</pre>
|
||||
*
|
||||
* one should use {@code t1 - t0 < 0}, not {@code t1 < t0},
|
||||
* <p>To compare elapsed time against a timeout, use <pre> {@code
|
||||
* if (System.nanoTime() - startTime >= timeoutNanos) ...}</pre>
|
||||
* instead of <pre> {@code
|
||||
* if (System.nanoTime() >= startTime + timeoutNanos) ...}</pre>
|
||||
* because of the possibility of numerical overflow.
|
||||
*
|
||||
* @return the current value of the running Java Virtual Machine's
|
||||
|
||||
@ -553,6 +553,12 @@ public interface Spliterator<T> {
|
||||
* sub-split size is known and additions or removals to the source are not
|
||||
* reflected when traversing.
|
||||
*
|
||||
* <p>A top-level Spliterator should not report both {@code CONCURRENT} and
|
||||
* {@code IMMUTABLE}, since they are mutually exclusive. Such a Spliterator
|
||||
* is inconsistent and no guarantees can be made about any computation using
|
||||
* that Spliterator. Sub-spliterators may report {@code IMMUTABLE} if
|
||||
* additions or removals to the source are not reflected when traversing.
|
||||
*
|
||||
* @apiNote Most concurrent collections maintain a consistency policy
|
||||
* guaranteeing accuracy with respect to elements present at the point of
|
||||
* Spliterator construction, but possibly not reflecting subsequent
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2000, 2015, 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
|
||||
@ -845,22 +845,6 @@ public final class Unsafe {
|
||||
public native Object allocateInstance(Class<?> cls)
|
||||
throws InstantiationException;
|
||||
|
||||
/** Lock the object. It must get unlocked via {@link #monitorExit}. */
|
||||
public native void monitorEnter(Object o);
|
||||
|
||||
/**
|
||||
* Unlock the object. It must have been locked via {@link
|
||||
* #monitorEnter}.
|
||||
*/
|
||||
public native void monitorExit(Object o);
|
||||
|
||||
/**
|
||||
* Tries to lock the object. Returns true or false to indicate
|
||||
* whether the lock succeeded. If it did, the object must be
|
||||
* unlocked via {@link #monitorExit}.
|
||||
*/
|
||||
public native boolean tryMonitorEnter(Object o);
|
||||
|
||||
/** Throw the exception without telling the verifier. */
|
||||
public native void throwException(Throwable ee);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2015, 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
|
||||
@ -25,24 +25,156 @@
|
||||
|
||||
package java.lang;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
import java.lang.ProcessBuilder.Redirect;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.security.AccessController;
|
||||
import static java.security.AccessController.doPrivileged;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
/**
|
||||
* This class is for the exclusive use of ProcessBuilder.start() to
|
||||
* create new processes.
|
||||
* This java.lang.Process subclass in the UNIX environment is for the exclusive use of
|
||||
* ProcessBuilder.start() to create new processes.
|
||||
*
|
||||
* @author Mario Wolczko and Ross Knippel.
|
||||
* @author Konstantin Kladko (ported to Linux and Bsd)
|
||||
* @author Martin Buchholz
|
||||
* @author Volker Simonis (ported to AIX)
|
||||
* @since 1.5
|
||||
*/
|
||||
final class ProcessImpl {
|
||||
final class ProcessImpl extends Process {
|
||||
private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
|
||||
= sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||
|
||||
private ProcessImpl() {} // Not instantiable
|
||||
private final int pid;
|
||||
private int exitcode;
|
||||
private boolean hasExited;
|
||||
|
||||
private /* final */ OutputStream stdin;
|
||||
private /* final */ InputStream stdout;
|
||||
private /* final */ InputStream stderr;
|
||||
|
||||
// only used on Solaris
|
||||
private /* final */ DeferredCloseInputStream stdout_inner_stream;
|
||||
|
||||
private static enum LaunchMechanism {
|
||||
// order IS important!
|
||||
FORK,
|
||||
POSIX_SPAWN,
|
||||
VFORK
|
||||
}
|
||||
|
||||
private static enum Platform {
|
||||
|
||||
LINUX(LaunchMechanism.VFORK, LaunchMechanism.FORK),
|
||||
|
||||
BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
|
||||
|
||||
SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
|
||||
|
||||
AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
|
||||
|
||||
final LaunchMechanism defaultLaunchMechanism;
|
||||
final Set<LaunchMechanism> validLaunchMechanisms;
|
||||
|
||||
Platform(LaunchMechanism ... launchMechanisms) {
|
||||
this.defaultLaunchMechanism = launchMechanisms[0];
|
||||
this.validLaunchMechanisms =
|
||||
EnumSet.copyOf(Arrays.asList(launchMechanisms));
|
||||
}
|
||||
|
||||
@SuppressWarnings("fallthrough")
|
||||
private String helperPath(String javahome, String osArch) {
|
||||
switch (this) {
|
||||
case SOLARIS:
|
||||
if (osArch.equals("x86")) { osArch = "i386"; }
|
||||
else if (osArch.equals("x86_64")) { osArch = "amd64"; }
|
||||
// fall through...
|
||||
case LINUX:
|
||||
case AIX:
|
||||
return javahome + "/lib/" + osArch + "/jspawnhelper";
|
||||
|
||||
case BSD:
|
||||
return javahome + "/lib/jspawnhelper";
|
||||
|
||||
default:
|
||||
throw new AssertionError("Unsupported platform: " + this);
|
||||
}
|
||||
}
|
||||
|
||||
String helperPath() {
|
||||
return AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () ->
|
||||
helperPath(System.getProperty("java.home"),
|
||||
System.getProperty("os.arch"))
|
||||
);
|
||||
}
|
||||
|
||||
LaunchMechanism launchMechanism() {
|
||||
return AccessController.doPrivileged(
|
||||
(PrivilegedAction<LaunchMechanism>) () -> {
|
||||
String s = System.getProperty(
|
||||
"jdk.lang.Process.launchMechanism");
|
||||
LaunchMechanism lm;
|
||||
if (s == null) {
|
||||
lm = defaultLaunchMechanism;
|
||||
s = lm.name().toLowerCase(Locale.ENGLISH);
|
||||
} else {
|
||||
try {
|
||||
lm = LaunchMechanism.valueOf(
|
||||
s.toUpperCase(Locale.ENGLISH));
|
||||
} catch (IllegalArgumentException e) {
|
||||
lm = null;
|
||||
}
|
||||
}
|
||||
if (lm == null || !validLaunchMechanisms.contains(lm)) {
|
||||
throw new Error(
|
||||
s + " is not a supported " +
|
||||
"process launch mechanism on this platform."
|
||||
);
|
||||
}
|
||||
return lm;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static Platform get() {
|
||||
String osName = AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () -> System.getProperty("os.name")
|
||||
);
|
||||
|
||||
if (osName.equals("Linux")) { return LINUX; }
|
||||
if (osName.contains("OS X")) { return BSD; }
|
||||
if (osName.equals("SunOS")) { return SOLARIS; }
|
||||
if (osName.equals("AIX")) { return AIX; }
|
||||
|
||||
throw new Error(osName + " is not a supported OS platform.");
|
||||
}
|
||||
}
|
||||
|
||||
private static final Platform platform = Platform.get();
|
||||
private static final LaunchMechanism launchMechanism = platform.launchMechanism();
|
||||
private static final byte[] helperpath = toCString(platform.helperPath());
|
||||
|
||||
/* this is for the reaping thread */
|
||||
private native int waitForProcessExit(int pid);
|
||||
|
||||
private static byte[] toCString(String s) {
|
||||
if (s == null)
|
||||
@ -50,8 +182,8 @@ final class ProcessImpl {
|
||||
byte[] bytes = s.getBytes();
|
||||
byte[] result = new byte[bytes.length + 1];
|
||||
System.arraycopy(bytes, 0,
|
||||
result, 0,
|
||||
bytes.length);
|
||||
result, 0,
|
||||
bytes.length);
|
||||
result[result.length-1] = (byte)0;
|
||||
return result;
|
||||
}
|
||||
@ -62,7 +194,7 @@ final class ProcessImpl {
|
||||
String dir,
|
||||
ProcessBuilder.Redirect[] redirects,
|
||||
boolean redirectErrorStream)
|
||||
throws IOException
|
||||
throws IOException
|
||||
{
|
||||
assert cmdarray != null && cmdarray.length > 0;
|
||||
|
||||
@ -112,7 +244,7 @@ final class ProcessImpl {
|
||||
std_fds[1] = 1;
|
||||
else {
|
||||
f1 = new FileOutputStream(redirects[1].file(),
|
||||
redirects[1].append());
|
||||
redirects[1].append());
|
||||
std_fds[1] = fdAccess.get(f1.getFD());
|
||||
}
|
||||
|
||||
@ -122,18 +254,18 @@ final class ProcessImpl {
|
||||
std_fds[2] = 2;
|
||||
else {
|
||||
f2 = new FileOutputStream(redirects[2].file(),
|
||||
redirects[2].append());
|
||||
redirects[2].append());
|
||||
std_fds[2] = fdAccess.get(f2.getFD());
|
||||
}
|
||||
}
|
||||
|
||||
return new UNIXProcess
|
||||
(toCString(cmdarray[0]),
|
||||
argBlock, args.length,
|
||||
envBlock, envc[0],
|
||||
toCString(dir),
|
||||
std_fds,
|
||||
redirectErrorStream);
|
||||
return new ProcessImpl
|
||||
(toCString(cmdarray[0]),
|
||||
argBlock, args.length,
|
||||
envBlock, envc[0],
|
||||
toCString(dir),
|
||||
std_fds,
|
||||
redirectErrorStream);
|
||||
} finally {
|
||||
// In theory, close() can throw IOException
|
||||
// (although it is rather unlikely to happen here)
|
||||
@ -144,4 +276,654 @@ final class ProcessImpl {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a process. Depending on the {@code mode} flag, this is done by
|
||||
* one of the following mechanisms:
|
||||
* <pre>
|
||||
* 1 - fork(2) and exec(2)
|
||||
* 2 - posix_spawn(3P)
|
||||
* 3 - vfork(2) and exec(2)
|
||||
*
|
||||
* (4 - clone(2) and exec(2) - obsolete and currently disabled in native code)
|
||||
* </pre>
|
||||
* @param fds an array of three file descriptors.
|
||||
* Indexes 0, 1, and 2 correspond to standard input,
|
||||
* standard output and standard error, respectively. On
|
||||
* input, a value of -1 means to create a pipe to connect
|
||||
* child and parent processes. On output, a value which
|
||||
* is not -1 is the parent pipe fd corresponding to the
|
||||
* pipe which has been created. An element of this array
|
||||
* is -1 on input if and only if it is <em>not</em> -1 on
|
||||
* output.
|
||||
* @return the pid of the subprocess
|
||||
*/
|
||||
private native int forkAndExec(int mode, byte[] helperpath,
|
||||
byte[] prog,
|
||||
byte[] argBlock, int argc,
|
||||
byte[] envBlock, int envc,
|
||||
byte[] dir,
|
||||
int[] fds,
|
||||
boolean redirectErrorStream)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* The thread pool of "process reaper" daemon threads.
|
||||
*/
|
||||
private static final Executor processReaperExecutor =
|
||||
doPrivileged((PrivilegedAction<Executor>) () -> {
|
||||
|
||||
ThreadGroup tg = Thread.currentThread().getThreadGroup();
|
||||
while (tg.getParent() != null) tg = tg.getParent();
|
||||
ThreadGroup systemThreadGroup = tg;
|
||||
|
||||
ThreadFactory threadFactory = grimReaper -> {
|
||||
// Our thread stack requirement is quite modest.
|
||||
Thread t = new Thread(systemThreadGroup, grimReaper,
|
||||
"process reaper", 32768);
|
||||
t.setDaemon(true);
|
||||
// A small attempt (probably futile) to avoid priority inversion
|
||||
t.setPriority(Thread.MAX_PRIORITY);
|
||||
return t;
|
||||
};
|
||||
|
||||
return Executors.newCachedThreadPool(threadFactory);
|
||||
});
|
||||
|
||||
private ProcessImpl(final byte[] prog,
|
||||
final byte[] argBlock, final int argc,
|
||||
final byte[] envBlock, final int envc,
|
||||
final byte[] dir,
|
||||
final int[] fds,
|
||||
final boolean redirectErrorStream)
|
||||
throws IOException {
|
||||
|
||||
pid = forkAndExec(launchMechanism.ordinal() + 1,
|
||||
helperpath,
|
||||
prog,
|
||||
argBlock, argc,
|
||||
envBlock, envc,
|
||||
dir,
|
||||
fds,
|
||||
redirectErrorStream);
|
||||
|
||||
try {
|
||||
doPrivileged((PrivilegedExceptionAction<Void>) () -> {
|
||||
initStreams(fds);
|
||||
return null;
|
||||
});
|
||||
} catch (PrivilegedActionException ex) {
|
||||
throw (IOException) ex.getException();
|
||||
}
|
||||
}
|
||||
|
||||
static FileDescriptor newFileDescriptor(int fd) {
|
||||
FileDescriptor fileDescriptor = new FileDescriptor();
|
||||
fdAccess.set(fileDescriptor, fd);
|
||||
return fileDescriptor;
|
||||
}
|
||||
|
||||
void initStreams(int[] fds) throws IOException {
|
||||
switch (platform) {
|
||||
case LINUX:
|
||||
case BSD:
|
||||
stdin = (fds[0] == -1) ?
|
||||
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||
new ProcessPipeOutputStream(fds[0]);
|
||||
|
||||
stdout = (fds[1] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new ProcessPipeInputStream(fds[1]);
|
||||
|
||||
stderr = (fds[2] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new ProcessPipeInputStream(fds[2]);
|
||||
|
||||
processReaperExecutor.execute(() -> {
|
||||
int exitcode = waitForProcessExit(pid);
|
||||
|
||||
synchronized (this) {
|
||||
this.exitcode = exitcode;
|
||||
this.hasExited = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
|
||||
if (stdout instanceof ProcessPipeInputStream)
|
||||
((ProcessPipeInputStream) stdout).processExited();
|
||||
|
||||
if (stderr instanceof ProcessPipeInputStream)
|
||||
((ProcessPipeInputStream) stderr).processExited();
|
||||
|
||||
if (stdin instanceof ProcessPipeOutputStream)
|
||||
((ProcessPipeOutputStream) stdin).processExited();
|
||||
});
|
||||
break;
|
||||
|
||||
case SOLARIS:
|
||||
stdin = (fds[0] == -1) ?
|
||||
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||
new BufferedOutputStream(
|
||||
new FileOutputStream(newFileDescriptor(fds[0])));
|
||||
|
||||
stdout = (fds[1] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new BufferedInputStream(
|
||||
stdout_inner_stream =
|
||||
new DeferredCloseInputStream(
|
||||
newFileDescriptor(fds[1])));
|
||||
|
||||
stderr = (fds[2] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new DeferredCloseInputStream(newFileDescriptor(fds[2]));
|
||||
|
||||
/*
|
||||
* For each subprocess forked a corresponding reaper task
|
||||
* is submitted. That task is the only thread which waits
|
||||
* for the subprocess to terminate and it doesn't hold any
|
||||
* locks while doing so. This design allows waitFor() and
|
||||
* exitStatus() to be safely executed in parallel (and they
|
||||
* need no native code).
|
||||
*/
|
||||
processReaperExecutor.execute(() -> {
|
||||
int exitcode = waitForProcessExit(pid);
|
||||
|
||||
synchronized (this) {
|
||||
this.exitcode = exitcode;
|
||||
this.hasExited = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case AIX:
|
||||
stdin = (fds[0] == -1) ?
|
||||
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||
new ProcessPipeOutputStream(fds[0]);
|
||||
|
||||
stdout = (fds[1] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new DeferredCloseProcessPipeInputStream(fds[1]);
|
||||
|
||||
stderr = (fds[2] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new DeferredCloseProcessPipeInputStream(fds[2]);
|
||||
|
||||
processReaperExecutor.execute(() -> {
|
||||
int exitcode = waitForProcessExit(pid);
|
||||
|
||||
synchronized (this) {
|
||||
this.exitcode = exitcode;
|
||||
this.hasExited = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
|
||||
if (stdout instanceof DeferredCloseProcessPipeInputStream)
|
||||
((DeferredCloseProcessPipeInputStream) stdout).processExited();
|
||||
|
||||
if (stderr instanceof DeferredCloseProcessPipeInputStream)
|
||||
((DeferredCloseProcessPipeInputStream) stderr).processExited();
|
||||
|
||||
if (stdin instanceof ProcessPipeOutputStream)
|
||||
((ProcessPipeOutputStream) stdin).processExited();
|
||||
});
|
||||
break;
|
||||
|
||||
default: throw new AssertionError("Unsupported platform: " + platform);
|
||||
}
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
return stdin;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return stdout;
|
||||
}
|
||||
|
||||
public InputStream getErrorStream() {
|
||||
return stderr;
|
||||
}
|
||||
|
||||
public synchronized int waitFor() throws InterruptedException {
|
||||
while (!hasExited) {
|
||||
wait();
|
||||
}
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean waitFor(long timeout, TimeUnit unit)
|
||||
throws InterruptedException
|
||||
{
|
||||
if (hasExited) return true;
|
||||
if (timeout <= 0) return false;
|
||||
|
||||
long remainingNanos = unit.toNanos(timeout);
|
||||
long deadline = System.nanoTime() + remainingNanos;
|
||||
|
||||
do {
|
||||
// Round up to next millisecond
|
||||
wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
|
||||
if (hasExited) {
|
||||
return true;
|
||||
}
|
||||
remainingNanos = deadline - System.nanoTime();
|
||||
} while (remainingNanos > 0);
|
||||
return hasExited;
|
||||
}
|
||||
|
||||
public synchronized int exitValue() {
|
||||
if (!hasExited) {
|
||||
throw new IllegalThreadStateException("process hasn't exited");
|
||||
}
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
private static native void destroyProcess(int pid, boolean force);
|
||||
|
||||
private void destroy(boolean force) {
|
||||
switch (platform) {
|
||||
case LINUX:
|
||||
case BSD:
|
||||
case AIX:
|
||||
// There is a risk that pid will be recycled, causing us to
|
||||
// kill the wrong process! So we only terminate processes
|
||||
// that appear to still be running. Even with this check,
|
||||
// there is an unavoidable race condition here, but the window
|
||||
// is very small, and OSes try hard to not recycle pids too
|
||||
// soon, so this is quite safe.
|
||||
synchronized (this) {
|
||||
if (!hasExited)
|
||||
destroyProcess(pid, force);
|
||||
}
|
||||
try { stdin.close(); } catch (IOException ignored) {}
|
||||
try { stdout.close(); } catch (IOException ignored) {}
|
||||
try { stderr.close(); } catch (IOException ignored) {}
|
||||
break;
|
||||
|
||||
case SOLARIS:
|
||||
// There is a risk that pid will be recycled, causing us to
|
||||
// kill the wrong process! So we only terminate processes
|
||||
// that appear to still be running. Even with this check,
|
||||
// there is an unavoidable race condition here, but the window
|
||||
// is very small, and OSes try hard to not recycle pids too
|
||||
// soon, so this is quite safe.
|
||||
synchronized (this) {
|
||||
if (!hasExited)
|
||||
destroyProcess(pid, force);
|
||||
try {
|
||||
stdin.close();
|
||||
if (stdout_inner_stream != null)
|
||||
stdout_inner_stream.closeDeferred(stdout);
|
||||
if (stderr instanceof DeferredCloseInputStream)
|
||||
((DeferredCloseInputStream) stderr)
|
||||
.closeDeferred(stderr);
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: throw new AssertionError("Unsupported platform: " + platform);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
destroy(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Process destroyForcibly() {
|
||||
destroy(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPid() {
|
||||
return pid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isAlive() {
|
||||
return !hasExited;
|
||||
}
|
||||
|
||||
private static native void init();
|
||||
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffered input stream for a subprocess pipe file descriptor
|
||||
* that allows the underlying file descriptor to be reclaimed when
|
||||
* the process exits, via the processExited hook.
|
||||
*
|
||||
* This is tricky because we do not want the user-level InputStream to be
|
||||
* closed until the user invokes close(), and we need to continue to be
|
||||
* able to read any buffered data lingering in the OS pipe buffer.
|
||||
*/
|
||||
private static class ProcessPipeInputStream extends BufferedInputStream {
|
||||
private final Object closeLock = new Object();
|
||||
|
||||
ProcessPipeInputStream(int fd) {
|
||||
super(new FileInputStream(newFileDescriptor(fd)));
|
||||
}
|
||||
private static byte[] drainInputStream(InputStream in)
|
||||
throws IOException {
|
||||
int n = 0;
|
||||
int j;
|
||||
byte[] a = null;
|
||||
while ((j = in.available()) > 0) {
|
||||
a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
|
||||
n += in.read(a, n, j);
|
||||
}
|
||||
return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
|
||||
}
|
||||
|
||||
/** Called by the process reaper thread when the process exits. */
|
||||
synchronized void processExited() {
|
||||
synchronized (closeLock) {
|
||||
try {
|
||||
InputStream in = this.in;
|
||||
// this stream is closed if and only if: in == null
|
||||
if (in != null) {
|
||||
byte[] stragglers = drainInputStream(in);
|
||||
in.close();
|
||||
this.in = (stragglers == null) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new ByteArrayInputStream(stragglers);
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// BufferedInputStream#close() is not synchronized unlike most other
|
||||
// methods. Synchronizing helps avoid race with processExited().
|
||||
synchronized (closeLock) {
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffered output stream for a subprocess pipe file descriptor
|
||||
* that allows the underlying file descriptor to be reclaimed when
|
||||
* the process exits, via the processExited hook.
|
||||
*/
|
||||
private static class ProcessPipeOutputStream extends BufferedOutputStream {
|
||||
ProcessPipeOutputStream(int fd) {
|
||||
super(new FileOutputStream(newFileDescriptor(fd)));
|
||||
}
|
||||
|
||||
/** Called by the process reaper thread when the process exits. */
|
||||
synchronized void processExited() {
|
||||
OutputStream out = this.out;
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException ignored) {
|
||||
// We know of no reason to get an IOException, but if
|
||||
// we do, there's nothing else to do but carry on.
|
||||
}
|
||||
this.out = ProcessBuilder.NullOutputStream.INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A FileInputStream that supports the deferment of the actual close
|
||||
// operation until the last pending I/O operation on the stream has
|
||||
// finished. This is required on Solaris because we must close the stdin
|
||||
// and stdout streams in the destroy method in order to reclaim the
|
||||
// underlying file descriptors. Doing so, however, causes any thread
|
||||
// currently blocked in a read on one of those streams to receive an
|
||||
// IOException("Bad file number"), which is incompatible with historical
|
||||
// behavior. By deferring the close we allow any pending reads to see -1
|
||||
// (EOF) as they did before.
|
||||
//
|
||||
private static class DeferredCloseInputStream extends FileInputStream
|
||||
{
|
||||
DeferredCloseInputStream(FileDescriptor fd) {
|
||||
super(fd);
|
||||
}
|
||||
|
||||
private Object lock = new Object(); // For the following fields
|
||||
private boolean closePending = false;
|
||||
private int useCount = 0;
|
||||
private InputStream streamToClose;
|
||||
|
||||
private void raise() {
|
||||
synchronized (lock) {
|
||||
useCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private void lower() throws IOException {
|
||||
synchronized (lock) {
|
||||
useCount--;
|
||||
if (useCount == 0 && closePending) {
|
||||
streamToClose.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stc is the actual stream to be closed; it might be this object, or
|
||||
// it might be an upstream object for which this object is downstream.
|
||||
//
|
||||
private void closeDeferred(InputStream stc) throws IOException {
|
||||
synchronized (lock) {
|
||||
if (useCount == 0) {
|
||||
stc.close();
|
||||
} else {
|
||||
closePending = true;
|
||||
streamToClose = stc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
synchronized (lock) {
|
||||
useCount = 0;
|
||||
closePending = false;
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read();
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
public int read(byte[] b) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read(b);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read(b, off, len);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
public long skip(long n) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.skip(n);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
public int available() throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.available();
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffered input stream for a subprocess pipe file descriptor
|
||||
* that allows the underlying file descriptor to be reclaimed when
|
||||
* the process exits, via the processExited hook.
|
||||
*
|
||||
* This is tricky because we do not want the user-level InputStream to be
|
||||
* closed until the user invokes close(), and we need to continue to be
|
||||
* able to read any buffered data lingering in the OS pipe buffer.
|
||||
*
|
||||
* On AIX this is especially tricky, because the 'close()' system call
|
||||
* will block if another thread is at the same time blocked in a file
|
||||
* operation (e.g. 'read()') on the same file descriptor. We therefore
|
||||
* combine 'ProcessPipeInputStream' approach used on Linux and Bsd
|
||||
* with the DeferredCloseInputStream approach used on Solaris. This means
|
||||
* that every potentially blocking operation on the file descriptor
|
||||
* increments a counter before it is executed and decrements it once it
|
||||
* finishes. The 'close()' operation will only be executed if there are
|
||||
* no pending operations. Otherwise it is deferred after the last pending
|
||||
* operation has finished.
|
||||
*
|
||||
*/
|
||||
private static class DeferredCloseProcessPipeInputStream
|
||||
extends BufferedInputStream {
|
||||
|
||||
private final Object closeLock = new Object();
|
||||
private int useCount = 0;
|
||||
private boolean closePending = false;
|
||||
|
||||
DeferredCloseProcessPipeInputStream(int fd) {
|
||||
super(new FileInputStream(newFileDescriptor(fd)));
|
||||
}
|
||||
|
||||
private InputStream drainInputStream(InputStream in)
|
||||
throws IOException {
|
||||
int n = 0;
|
||||
int j;
|
||||
byte[] a = null;
|
||||
synchronized (closeLock) {
|
||||
if (buf == null) // asynchronous close()?
|
||||
return null; // discard
|
||||
j = in.available();
|
||||
}
|
||||
while (j > 0) {
|
||||
a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
|
||||
synchronized (closeLock) {
|
||||
if (buf == null) // asynchronous close()?
|
||||
return null; // discard
|
||||
n += in.read(a, n, j);
|
||||
j = in.available();
|
||||
}
|
||||
}
|
||||
return (a == null) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
|
||||
}
|
||||
|
||||
/** Called by the process reaper thread when the process exits. */
|
||||
synchronized void processExited() {
|
||||
try {
|
||||
InputStream in = this.in;
|
||||
if (in != null) {
|
||||
InputStream stragglers = drainInputStream(in);
|
||||
in.close();
|
||||
this.in = stragglers;
|
||||
}
|
||||
} catch (IOException ignored) { }
|
||||
}
|
||||
|
||||
private void raise() {
|
||||
synchronized (closeLock) {
|
||||
useCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private void lower() throws IOException {
|
||||
synchronized (closeLock) {
|
||||
useCount--;
|
||||
if (useCount == 0 && closePending) {
|
||||
closePending = false;
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read();
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read(b);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read(b, off, len);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.skip(n);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.available();
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// BufferedInputStream#close() is not synchronized unlike most other
|
||||
// methods. Synchronizing helps avoid racing with drainInputStream().
|
||||
synchronized (closeLock) {
|
||||
if (useCount == 0) {
|
||||
super.close();
|
||||
}
|
||||
else {
|
||||
closePending = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,836 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2014, 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.
|
||||
*/
|
||||
|
||||
package java.lang;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.security.AccessController;
|
||||
import static java.security.AccessController.doPrivileged;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
|
||||
/**
|
||||
* java.lang.Process subclass in the UNIX environment.
|
||||
*
|
||||
* @author Mario Wolczko and Ross Knippel.
|
||||
* @author Konstantin Kladko (ported to Linux and Bsd)
|
||||
* @author Martin Buchholz
|
||||
* @author Volker Simonis (ported to AIX)
|
||||
*/
|
||||
final class UNIXProcess extends Process {
|
||||
private static final sun.misc.JavaIOFileDescriptorAccess fdAccess
|
||||
= sun.misc.SharedSecrets.getJavaIOFileDescriptorAccess();
|
||||
|
||||
private final int pid;
|
||||
private int exitcode;
|
||||
private boolean hasExited;
|
||||
|
||||
private /* final */ OutputStream stdin;
|
||||
private /* final */ InputStream stdout;
|
||||
private /* final */ InputStream stderr;
|
||||
|
||||
// only used on Solaris
|
||||
private /* final */ DeferredCloseInputStream stdout_inner_stream;
|
||||
|
||||
private static enum LaunchMechanism {
|
||||
// order IS important!
|
||||
FORK,
|
||||
POSIX_SPAWN,
|
||||
VFORK
|
||||
}
|
||||
|
||||
private static enum Platform {
|
||||
|
||||
LINUX(LaunchMechanism.VFORK, LaunchMechanism.FORK),
|
||||
|
||||
BSD(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
|
||||
|
||||
SOLARIS(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK),
|
||||
|
||||
AIX(LaunchMechanism.POSIX_SPAWN, LaunchMechanism.FORK);
|
||||
|
||||
final LaunchMechanism defaultLaunchMechanism;
|
||||
final Set<LaunchMechanism> validLaunchMechanisms;
|
||||
|
||||
Platform(LaunchMechanism ... launchMechanisms) {
|
||||
this.defaultLaunchMechanism = launchMechanisms[0];
|
||||
this.validLaunchMechanisms =
|
||||
EnumSet.copyOf(Arrays.asList(launchMechanisms));
|
||||
}
|
||||
|
||||
@SuppressWarnings("fallthrough")
|
||||
private String helperPath(String javahome, String osArch) {
|
||||
switch (this) {
|
||||
case SOLARIS:
|
||||
if (osArch.equals("x86")) { osArch = "i386"; }
|
||||
else if (osArch.equals("x86_64")) { osArch = "amd64"; }
|
||||
// fall through...
|
||||
case LINUX:
|
||||
case AIX:
|
||||
return javahome + "/lib/" + osArch + "/jspawnhelper";
|
||||
|
||||
case BSD:
|
||||
return javahome + "/lib/jspawnhelper";
|
||||
|
||||
default:
|
||||
throw new AssertionError("Unsupported platform: " + this);
|
||||
}
|
||||
}
|
||||
|
||||
String helperPath() {
|
||||
return AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () ->
|
||||
helperPath(System.getProperty("java.home"),
|
||||
System.getProperty("os.arch"))
|
||||
);
|
||||
}
|
||||
|
||||
LaunchMechanism launchMechanism() {
|
||||
return AccessController.doPrivileged(
|
||||
(PrivilegedAction<LaunchMechanism>) () -> {
|
||||
String s = System.getProperty(
|
||||
"jdk.lang.Process.launchMechanism");
|
||||
LaunchMechanism lm;
|
||||
if (s == null) {
|
||||
lm = defaultLaunchMechanism;
|
||||
s = lm.name().toLowerCase(Locale.ENGLISH);
|
||||
} else {
|
||||
try {
|
||||
lm = LaunchMechanism.valueOf(
|
||||
s.toUpperCase(Locale.ENGLISH));
|
||||
} catch (IllegalArgumentException e) {
|
||||
lm = null;
|
||||
}
|
||||
}
|
||||
if (lm == null || !validLaunchMechanisms.contains(lm)) {
|
||||
throw new Error(
|
||||
s + " is not a supported " +
|
||||
"process launch mechanism on this platform."
|
||||
);
|
||||
}
|
||||
return lm;
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
static Platform get() {
|
||||
String osName = AccessController.doPrivileged(
|
||||
(PrivilegedAction<String>) () -> System.getProperty("os.name")
|
||||
);
|
||||
|
||||
if (osName.equals("Linux")) { return LINUX; }
|
||||
if (osName.contains("OS X")) { return BSD; }
|
||||
if (osName.equals("SunOS")) { return SOLARIS; }
|
||||
if (osName.equals("AIX")) { return AIX; }
|
||||
|
||||
throw new Error(osName + " is not a supported OS platform.");
|
||||
}
|
||||
}
|
||||
|
||||
private static final Platform platform = Platform.get();
|
||||
private static final LaunchMechanism launchMechanism = platform.launchMechanism();
|
||||
private static final byte[] helperpath = toCString(platform.helperPath());
|
||||
|
||||
private static byte[] toCString(String s) {
|
||||
if (s == null)
|
||||
return null;
|
||||
byte[] bytes = s.getBytes();
|
||||
byte[] result = new byte[bytes.length + 1];
|
||||
System.arraycopy(bytes, 0,
|
||||
result, 0,
|
||||
bytes.length);
|
||||
result[result.length-1] = (byte)0;
|
||||
return result;
|
||||
}
|
||||
|
||||
/* this is for the reaping thread */
|
||||
private native int waitForProcessExit(int pid);
|
||||
|
||||
/**
|
||||
* Creates a process. Depending on the {@code mode} flag, this is done by
|
||||
* one of the following mechanisms:
|
||||
* <pre>
|
||||
* 1 - fork(2) and exec(2)
|
||||
* 2 - posix_spawn(3P)
|
||||
* 3 - vfork(2) and exec(2)
|
||||
*
|
||||
* (4 - clone(2) and exec(2) - obsolete and currently disabled in native code)
|
||||
* </pre>
|
||||
* @param fds an array of three file descriptors.
|
||||
* Indexes 0, 1, and 2 correspond to standard input,
|
||||
* standard output and standard error, respectively. On
|
||||
* input, a value of -1 means to create a pipe to connect
|
||||
* child and parent processes. On output, a value which
|
||||
* is not -1 is the parent pipe fd corresponding to the
|
||||
* pipe which has been created. An element of this array
|
||||
* is -1 on input if and only if it is <em>not</em> -1 on
|
||||
* output.
|
||||
* @return the pid of the subprocess
|
||||
*/
|
||||
private native int forkAndExec(int mode, byte[] helperpath,
|
||||
byte[] prog,
|
||||
byte[] argBlock, int argc,
|
||||
byte[] envBlock, int envc,
|
||||
byte[] dir,
|
||||
int[] fds,
|
||||
boolean redirectErrorStream)
|
||||
throws IOException;
|
||||
|
||||
/**
|
||||
* The thread pool of "process reaper" daemon threads.
|
||||
*/
|
||||
private static final Executor processReaperExecutor =
|
||||
doPrivileged((PrivilegedAction<Executor>) () -> {
|
||||
|
||||
ThreadGroup tg = Thread.currentThread().getThreadGroup();
|
||||
while (tg.getParent() != null) tg = tg.getParent();
|
||||
ThreadGroup systemThreadGroup = tg;
|
||||
|
||||
ThreadFactory threadFactory = grimReaper -> {
|
||||
// Our thread stack requirement is quite modest.
|
||||
Thread t = new Thread(systemThreadGroup, grimReaper,
|
||||
"process reaper", 32768);
|
||||
t.setDaemon(true);
|
||||
// A small attempt (probably futile) to avoid priority inversion
|
||||
t.setPriority(Thread.MAX_PRIORITY);
|
||||
return t;
|
||||
};
|
||||
|
||||
return Executors.newCachedThreadPool(threadFactory);
|
||||
});
|
||||
|
||||
UNIXProcess(final byte[] prog,
|
||||
final byte[] argBlock, final int argc,
|
||||
final byte[] envBlock, final int envc,
|
||||
final byte[] dir,
|
||||
final int[] fds,
|
||||
final boolean redirectErrorStream)
|
||||
throws IOException {
|
||||
|
||||
pid = forkAndExec(launchMechanism.ordinal() + 1,
|
||||
helperpath,
|
||||
prog,
|
||||
argBlock, argc,
|
||||
envBlock, envc,
|
||||
dir,
|
||||
fds,
|
||||
redirectErrorStream);
|
||||
|
||||
try {
|
||||
doPrivileged((PrivilegedExceptionAction<Void>) () -> {
|
||||
initStreams(fds);
|
||||
return null;
|
||||
});
|
||||
} catch (PrivilegedActionException ex) {
|
||||
throw (IOException) ex.getException();
|
||||
}
|
||||
}
|
||||
|
||||
static FileDescriptor newFileDescriptor(int fd) {
|
||||
FileDescriptor fileDescriptor = new FileDescriptor();
|
||||
fdAccess.set(fileDescriptor, fd);
|
||||
return fileDescriptor;
|
||||
}
|
||||
|
||||
void initStreams(int[] fds) throws IOException {
|
||||
switch (platform) {
|
||||
case LINUX:
|
||||
case BSD:
|
||||
stdin = (fds[0] == -1) ?
|
||||
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||
new ProcessPipeOutputStream(fds[0]);
|
||||
|
||||
stdout = (fds[1] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new ProcessPipeInputStream(fds[1]);
|
||||
|
||||
stderr = (fds[2] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new ProcessPipeInputStream(fds[2]);
|
||||
|
||||
processReaperExecutor.execute(() -> {
|
||||
int exitcode = waitForProcessExit(pid);
|
||||
|
||||
synchronized (this) {
|
||||
this.exitcode = exitcode;
|
||||
this.hasExited = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
|
||||
if (stdout instanceof ProcessPipeInputStream)
|
||||
((ProcessPipeInputStream) stdout).processExited();
|
||||
|
||||
if (stderr instanceof ProcessPipeInputStream)
|
||||
((ProcessPipeInputStream) stderr).processExited();
|
||||
|
||||
if (stdin instanceof ProcessPipeOutputStream)
|
||||
((ProcessPipeOutputStream) stdin).processExited();
|
||||
});
|
||||
break;
|
||||
|
||||
case SOLARIS:
|
||||
stdin = (fds[0] == -1) ?
|
||||
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||
new BufferedOutputStream(
|
||||
new FileOutputStream(newFileDescriptor(fds[0])));
|
||||
|
||||
stdout = (fds[1] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new BufferedInputStream(
|
||||
stdout_inner_stream =
|
||||
new DeferredCloseInputStream(
|
||||
newFileDescriptor(fds[1])));
|
||||
|
||||
stderr = (fds[2] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new DeferredCloseInputStream(newFileDescriptor(fds[2]));
|
||||
|
||||
/*
|
||||
* For each subprocess forked a corresponding reaper task
|
||||
* is submitted. That task is the only thread which waits
|
||||
* for the subprocess to terminate and it doesn't hold any
|
||||
* locks while doing so. This design allows waitFor() and
|
||||
* exitStatus() to be safely executed in parallel (and they
|
||||
* need no native code).
|
||||
*/
|
||||
processReaperExecutor.execute(() -> {
|
||||
int exitcode = waitForProcessExit(pid);
|
||||
|
||||
synchronized (this) {
|
||||
this.exitcode = exitcode;
|
||||
this.hasExited = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
case AIX:
|
||||
stdin = (fds[0] == -1) ?
|
||||
ProcessBuilder.NullOutputStream.INSTANCE :
|
||||
new ProcessPipeOutputStream(fds[0]);
|
||||
|
||||
stdout = (fds[1] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new DeferredCloseProcessPipeInputStream(fds[1]);
|
||||
|
||||
stderr = (fds[2] == -1) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new DeferredCloseProcessPipeInputStream(fds[2]);
|
||||
|
||||
processReaperExecutor.execute(() -> {
|
||||
int exitcode = waitForProcessExit(pid);
|
||||
|
||||
synchronized (this) {
|
||||
this.exitcode = exitcode;
|
||||
this.hasExited = true;
|
||||
this.notifyAll();
|
||||
}
|
||||
|
||||
if (stdout instanceof DeferredCloseProcessPipeInputStream)
|
||||
((DeferredCloseProcessPipeInputStream) stdout).processExited();
|
||||
|
||||
if (stderr instanceof DeferredCloseProcessPipeInputStream)
|
||||
((DeferredCloseProcessPipeInputStream) stderr).processExited();
|
||||
|
||||
if (stdin instanceof ProcessPipeOutputStream)
|
||||
((ProcessPipeOutputStream) stdin).processExited();
|
||||
});
|
||||
break;
|
||||
|
||||
default: throw new AssertionError("Unsupported platform: " + platform);
|
||||
}
|
||||
}
|
||||
|
||||
public OutputStream getOutputStream() {
|
||||
return stdin;
|
||||
}
|
||||
|
||||
public InputStream getInputStream() {
|
||||
return stdout;
|
||||
}
|
||||
|
||||
public InputStream getErrorStream() {
|
||||
return stderr;
|
||||
}
|
||||
|
||||
public synchronized int waitFor() throws InterruptedException {
|
||||
while (!hasExited) {
|
||||
wait();
|
||||
}
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean waitFor(long timeout, TimeUnit unit)
|
||||
throws InterruptedException
|
||||
{
|
||||
if (hasExited) return true;
|
||||
if (timeout <= 0) return false;
|
||||
|
||||
long remainingNanos = unit.toNanos(timeout);
|
||||
long deadline = System.nanoTime() + remainingNanos;
|
||||
|
||||
do {
|
||||
// Round up to next millisecond
|
||||
wait(TimeUnit.NANOSECONDS.toMillis(remainingNanos + 999_999L));
|
||||
if (hasExited) {
|
||||
return true;
|
||||
}
|
||||
remainingNanos = deadline - System.nanoTime();
|
||||
} while (remainingNanos > 0);
|
||||
return hasExited;
|
||||
}
|
||||
|
||||
public synchronized int exitValue() {
|
||||
if (!hasExited) {
|
||||
throw new IllegalThreadStateException("process hasn't exited");
|
||||
}
|
||||
return exitcode;
|
||||
}
|
||||
|
||||
private static native void destroyProcess(int pid, boolean force);
|
||||
|
||||
private void destroy(boolean force) {
|
||||
switch (platform) {
|
||||
case LINUX:
|
||||
case BSD:
|
||||
case AIX:
|
||||
// There is a risk that pid will be recycled, causing us to
|
||||
// kill the wrong process! So we only terminate processes
|
||||
// that appear to still be running. Even with this check,
|
||||
// there is an unavoidable race condition here, but the window
|
||||
// is very small, and OSes try hard to not recycle pids too
|
||||
// soon, so this is quite safe.
|
||||
synchronized (this) {
|
||||
if (!hasExited)
|
||||
destroyProcess(pid, force);
|
||||
}
|
||||
try { stdin.close(); } catch (IOException ignored) {}
|
||||
try { stdout.close(); } catch (IOException ignored) {}
|
||||
try { stderr.close(); } catch (IOException ignored) {}
|
||||
break;
|
||||
|
||||
case SOLARIS:
|
||||
// There is a risk that pid will be recycled, causing us to
|
||||
// kill the wrong process! So we only terminate processes
|
||||
// that appear to still be running. Even with this check,
|
||||
// there is an unavoidable race condition here, but the window
|
||||
// is very small, and OSes try hard to not recycle pids too
|
||||
// soon, so this is quite safe.
|
||||
synchronized (this) {
|
||||
if (!hasExited)
|
||||
destroyProcess(pid, force);
|
||||
try {
|
||||
stdin.close();
|
||||
if (stdout_inner_stream != null)
|
||||
stdout_inner_stream.closeDeferred(stdout);
|
||||
if (stderr instanceof DeferredCloseInputStream)
|
||||
((DeferredCloseInputStream) stderr)
|
||||
.closeDeferred(stderr);
|
||||
} catch (IOException e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default: throw new AssertionError("Unsupported platform: " + platform);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
destroy(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Process destroyForcibly() {
|
||||
destroy(true);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getPid() {
|
||||
return pid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean isAlive() {
|
||||
return !hasExited;
|
||||
}
|
||||
|
||||
private static native void init();
|
||||
|
||||
static {
|
||||
init();
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffered input stream for a subprocess pipe file descriptor
|
||||
* that allows the underlying file descriptor to be reclaimed when
|
||||
* the process exits, via the processExited hook.
|
||||
*
|
||||
* This is tricky because we do not want the user-level InputStream to be
|
||||
* closed until the user invokes close(), and we need to continue to be
|
||||
* able to read any buffered data lingering in the OS pipe buffer.
|
||||
*/
|
||||
private static class ProcessPipeInputStream extends BufferedInputStream {
|
||||
private final Object closeLock = new Object();
|
||||
|
||||
ProcessPipeInputStream(int fd) {
|
||||
super(new FileInputStream(newFileDescriptor(fd)));
|
||||
}
|
||||
private static byte[] drainInputStream(InputStream in)
|
||||
throws IOException {
|
||||
int n = 0;
|
||||
int j;
|
||||
byte[] a = null;
|
||||
while ((j = in.available()) > 0) {
|
||||
a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
|
||||
n += in.read(a, n, j);
|
||||
}
|
||||
return (a == null || n == a.length) ? a : Arrays.copyOf(a, n);
|
||||
}
|
||||
|
||||
/** Called by the process reaper thread when the process exits. */
|
||||
synchronized void processExited() {
|
||||
synchronized (closeLock) {
|
||||
try {
|
||||
InputStream in = this.in;
|
||||
// this stream is closed if and only if: in == null
|
||||
if (in != null) {
|
||||
byte[] stragglers = drainInputStream(in);
|
||||
in.close();
|
||||
this.in = (stragglers == null) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new ByteArrayInputStream(stragglers);
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// BufferedInputStream#close() is not synchronized unlike most other
|
||||
// methods. Synchronizing helps avoid race with processExited().
|
||||
synchronized (closeLock) {
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffered output stream for a subprocess pipe file descriptor
|
||||
* that allows the underlying file descriptor to be reclaimed when
|
||||
* the process exits, via the processExited hook.
|
||||
*/
|
||||
private static class ProcessPipeOutputStream extends BufferedOutputStream {
|
||||
ProcessPipeOutputStream(int fd) {
|
||||
super(new FileOutputStream(newFileDescriptor(fd)));
|
||||
}
|
||||
|
||||
/** Called by the process reaper thread when the process exits. */
|
||||
synchronized void processExited() {
|
||||
OutputStream out = this.out;
|
||||
if (out != null) {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException ignored) {
|
||||
// We know of no reason to get an IOException, but if
|
||||
// we do, there's nothing else to do but carry on.
|
||||
}
|
||||
this.out = ProcessBuilder.NullOutputStream.INSTANCE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A FileInputStream that supports the deferment of the actual close
|
||||
// operation until the last pending I/O operation on the stream has
|
||||
// finished. This is required on Solaris because we must close the stdin
|
||||
// and stdout streams in the destroy method in order to reclaim the
|
||||
// underlying file descriptors. Doing so, however, causes any thread
|
||||
// currently blocked in a read on one of those streams to receive an
|
||||
// IOException("Bad file number"), which is incompatible with historical
|
||||
// behavior. By deferring the close we allow any pending reads to see -1
|
||||
// (EOF) as they did before.
|
||||
//
|
||||
private static class DeferredCloseInputStream extends FileInputStream
|
||||
{
|
||||
DeferredCloseInputStream(FileDescriptor fd) {
|
||||
super(fd);
|
||||
}
|
||||
|
||||
private Object lock = new Object(); // For the following fields
|
||||
private boolean closePending = false;
|
||||
private int useCount = 0;
|
||||
private InputStream streamToClose;
|
||||
|
||||
private void raise() {
|
||||
synchronized (lock) {
|
||||
useCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private void lower() throws IOException {
|
||||
synchronized (lock) {
|
||||
useCount--;
|
||||
if (useCount == 0 && closePending) {
|
||||
streamToClose.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// stc is the actual stream to be closed; it might be this object, or
|
||||
// it might be an upstream object for which this object is downstream.
|
||||
//
|
||||
private void closeDeferred(InputStream stc) throws IOException {
|
||||
synchronized (lock) {
|
||||
if (useCount == 0) {
|
||||
stc.close();
|
||||
} else {
|
||||
closePending = true;
|
||||
streamToClose = stc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
synchronized (lock) {
|
||||
useCount = 0;
|
||||
closePending = false;
|
||||
}
|
||||
super.close();
|
||||
}
|
||||
|
||||
public int read() throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read();
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
public int read(byte[] b) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read(b);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read(b, off, len);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
public long skip(long n) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.skip(n);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
public int available() throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.available();
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A buffered input stream for a subprocess pipe file descriptor
|
||||
* that allows the underlying file descriptor to be reclaimed when
|
||||
* the process exits, via the processExited hook.
|
||||
*
|
||||
* This is tricky because we do not want the user-level InputStream to be
|
||||
* closed until the user invokes close(), and we need to continue to be
|
||||
* able to read any buffered data lingering in the OS pipe buffer.
|
||||
*
|
||||
* On AIX this is especially tricky, because the 'close()' system call
|
||||
* will block if another thread is at the same time blocked in a file
|
||||
* operation (e.g. 'read()') on the same file descriptor. We therefore
|
||||
* combine 'ProcessPipeInputStream' approach used on Linux and Bsd
|
||||
* with the DeferredCloseInputStream approach used on Solaris. This means
|
||||
* that every potentially blocking operation on the file descriptor
|
||||
* increments a counter before it is executed and decrements it once it
|
||||
* finishes. The 'close()' operation will only be executed if there are
|
||||
* no pending operations. Otherwise it is deferred after the last pending
|
||||
* operation has finished.
|
||||
*
|
||||
*/
|
||||
private static class DeferredCloseProcessPipeInputStream
|
||||
extends BufferedInputStream {
|
||||
|
||||
private final Object closeLock = new Object();
|
||||
private int useCount = 0;
|
||||
private boolean closePending = false;
|
||||
|
||||
DeferredCloseProcessPipeInputStream(int fd) {
|
||||
super(new FileInputStream(newFileDescriptor(fd)));
|
||||
}
|
||||
|
||||
private InputStream drainInputStream(InputStream in)
|
||||
throws IOException {
|
||||
int n = 0;
|
||||
int j;
|
||||
byte[] a = null;
|
||||
synchronized (closeLock) {
|
||||
if (buf == null) // asynchronous close()?
|
||||
return null; // discard
|
||||
j = in.available();
|
||||
}
|
||||
while (j > 0) {
|
||||
a = (a == null) ? new byte[j] : Arrays.copyOf(a, n + j);
|
||||
synchronized (closeLock) {
|
||||
if (buf == null) // asynchronous close()?
|
||||
return null; // discard
|
||||
n += in.read(a, n, j);
|
||||
j = in.available();
|
||||
}
|
||||
}
|
||||
return (a == null) ?
|
||||
ProcessBuilder.NullInputStream.INSTANCE :
|
||||
new ByteArrayInputStream(n == a.length ? a : Arrays.copyOf(a, n));
|
||||
}
|
||||
|
||||
/** Called by the process reaper thread when the process exits. */
|
||||
synchronized void processExited() {
|
||||
try {
|
||||
InputStream in = this.in;
|
||||
if (in != null) {
|
||||
InputStream stragglers = drainInputStream(in);
|
||||
in.close();
|
||||
this.in = stragglers;
|
||||
}
|
||||
} catch (IOException ignored) { }
|
||||
}
|
||||
|
||||
private void raise() {
|
||||
synchronized (closeLock) {
|
||||
useCount++;
|
||||
}
|
||||
}
|
||||
|
||||
private void lower() throws IOException {
|
||||
synchronized (closeLock) {
|
||||
useCount--;
|
||||
if (useCount == 0 && closePending) {
|
||||
closePending = false;
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read();
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read(b);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.read(b, off, len);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.skip(n);
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
raise();
|
||||
try {
|
||||
return super.available();
|
||||
} finally {
|
||||
lower();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
// BufferedInputStream#close() is not synchronized unlike most other
|
||||
// methods. Synchronizing helps avoid racing with drainInputStream().
|
||||
synchronized (closeLock) {
|
||||
if (useCount == 0) {
|
||||
super.close();
|
||||
}
|
||||
else {
|
||||
closePending = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 1995, 2015, 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
|
||||
@ -203,7 +203,7 @@ effectivePathv(JNIEnv *env)
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_lang_UNIXProcess_init(JNIEnv *env, jclass clazz)
|
||||
Java_java_lang_ProcessImpl_init(JNIEnv *env, jclass clazz)
|
||||
{
|
||||
parentPathv = effectivePathv(env);
|
||||
CHECK_NULL(parentPathv);
|
||||
@ -230,7 +230,7 @@ Java_java_lang_UNIXProcess_init(JNIEnv *env, jclass clazz)
|
||||
/* Block until a child process exits and return its exit code.
|
||||
Note, can only be called once for any given pid. */
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_lang_UNIXProcess_waitForProcessExit(JNIEnv* env,
|
||||
Java_java_lang_ProcessImpl_waitForProcessExit(JNIEnv* env,
|
||||
jobject junk,
|
||||
jint pid)
|
||||
{
|
||||
@ -562,7 +562,7 @@ startChild(JNIEnv *env, jobject process, ChildStuff *c, const char *helperpath)
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
|
||||
Java_java_lang_ProcessImpl_forkAndExec(JNIEnv *env,
|
||||
jobject process,
|
||||
jint mode,
|
||||
jbyteArray helperpath,
|
||||
@ -714,7 +714,7 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env,
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_java_lang_UNIXProcess_destroyProcess(JNIEnv *env,
|
||||
Java_java_lang_ProcessImpl_destroyProcess(JNIEnv *env,
|
||||
jobject junk,
|
||||
jint pid,
|
||||
jboolean force)
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2015, 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 @@ extern char **environ;
|
||||
} while((_result == -1) && (errno == EINTR)); \
|
||||
} while(0)
|
||||
|
||||
/* These numbers must be the same as the Enum in UNIXProcess.java
|
||||
/* These numbers must be the same as the Enum in ProcessImpl.java
|
||||
* Must be a better way of doing this.
|
||||
*/
|
||||
#define MODE_FORK 1
|
||||
|
||||
@ -48,6 +48,8 @@ JNIEXPORT void JNICALL Java_java_net_DualStackPlainSocketImpl_initIDs
|
||||
isa_ctorID = (*env)->GetMethodID(env, cls, "<init>",
|
||||
"(Ljava/net/InetAddress;I)V");
|
||||
|
||||
initInetAddressIDs(env);
|
||||
|
||||
// implement read timeout with select.
|
||||
isRcvTimeoutSupported = 0;
|
||||
}
|
||||
@ -294,6 +296,8 @@ JNIEXPORT jint JNICALL Java_java_net_DualStackPlainSocketImpl_accept0
|
||||
return -1;
|
||||
}
|
||||
|
||||
SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
|
||||
|
||||
ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, &port);
|
||||
isa = (*env)->NewObject(env, isa_class, isa_ctorID, ia, port);
|
||||
(*env)->SetObjectArrayElement(env, isaa, 0, isa);
|
||||
|
||||
@ -699,6 +699,7 @@ Java_java_net_TwoStacksPlainSocketImpl_socketAccept(JNIEnv *env, jobject this,
|
||||
}
|
||||
return;
|
||||
}
|
||||
SetHandleInformation((HANDLE)(UINT_PTR)fd, HANDLE_FLAG_INHERIT, 0);
|
||||
(*env)->SetIntField(env, socketFdObj, IO_fd_fdID, fd);
|
||||
|
||||
if (him.him.sa_family == AF_INET) {
|
||||
|
||||
@ -105,6 +105,7 @@ Java_sun_nio_ch_ServerSocketChannelImpl_accept0(JNIEnv *env, jobject this,
|
||||
return IOS_THROWN;
|
||||
}
|
||||
|
||||
SetHandleInformation((HANDLE)(UINT_PTR)newfd, HANDLE_FLAG_INHERIT, 0);
|
||||
(*env)->SetIntField(env, newfdo, fd_fdID, newfd);
|
||||
remote_ia = NET_SockaddrToInetAddress(env, (struct sockaddr *)&sa, (int *)&remote_port);
|
||||
CHECK_NULL_RETURN(remote_ia, IOS_THROWN);
|
||||
|
||||
@ -913,9 +913,9 @@ public class Config {
|
||||
|
||||
private static String unquote(String s) {
|
||||
s = s.trim();
|
||||
if (s.isEmpty()) return s;
|
||||
if (s.charAt(0) == '"' && s.charAt(s.length()-1) == '"' ||
|
||||
s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\'') {
|
||||
if (s.length() >= 2 &&
|
||||
((s.charAt(0) == '"' && s.charAt(s.length()-1) == '"') ||
|
||||
(s.charAt(0) == '\'' && s.charAt(s.length()-1) == '\''))) {
|
||||
s = s.substring(1, s.length()-1).trim();
|
||||
}
|
||||
return s;
|
||||
|
||||
@ -62,7 +62,8 @@ abstract class KrbKdcRep {
|
||||
throw new KrbApErrException(Krb5.KRB_AP_ERR_MODIFIED);
|
||||
}
|
||||
|
||||
for (int i = 1; i < 6; i++) {
|
||||
// We allow KDC to return a non-forwardable ticket if request has -f
|
||||
for (int i = 2; i < 6; i++) {
|
||||
if (req.reqBody.kdcOptions.get(i) !=
|
||||
rep.encKDCRepPart.flags.get(i)) {
|
||||
if (Krb5.DEBUG) {
|
||||
|
||||
@ -149,19 +149,11 @@ public class KrbTgsReq {
|
||||
ctime = KerberosTime.now();
|
||||
|
||||
// check if they are valid arguments. The optional fields
|
||||
// should be consistent with settings in KDCOptions.
|
||||
|
||||
// TODO: Is this necessary? If the TGT is not FORWARDABLE,
|
||||
// you can still request for a FORWARDABLE ticket, just the
|
||||
// KDC will give you a non-FORWARDABLE one. Even if you
|
||||
// cannot use the ticket expected, it still contains info.
|
||||
// This means there will be problem later. We already have
|
||||
// flags check in KrbTgsRep. Of course, sometimes the KDC
|
||||
// will not issue the ticket at all.
|
||||
// should be consistent with settings in KDCOptions.
|
||||
|
||||
if (options.get(KDCOptions.FORWARDABLE) &&
|
||||
(!(asCreds.flags.get(Krb5.TKT_OPTS_FORWARDABLE)))) {
|
||||
throw new KrbException(Krb5.KRB_AP_ERR_REQ_OPTIONS);
|
||||
options.set(KDCOptions.FORWARDABLE, false);
|
||||
}
|
||||
if (options.get(KDCOptions.FORWARDED)) {
|
||||
if (!(asCreds.flags.get(KDCOptions.FORWARDABLE)))
|
||||
|
||||
@ -58,6 +58,9 @@ public class CredentialsUtil {
|
||||
// TODO: we do not support kerberos referral now
|
||||
throw new KrbException("Cross realm impersonation not supported");
|
||||
}
|
||||
if (!ccreds.isForwardable()) {
|
||||
throw new KrbException("S4U2self needs a FORWARDABLE ticket");
|
||||
}
|
||||
KrbTgsReq req = new KrbTgsReq(
|
||||
ccreds,
|
||||
ccreds.getClient(),
|
||||
@ -68,6 +71,9 @@ public class CredentialsUtil {
|
||||
if (!creds.getClient().equals(client)) {
|
||||
throw new KrbException("S4U2self request not honored by KDC");
|
||||
}
|
||||
if (!creds.isForwardable()) {
|
||||
throw new KrbException("S4U2self ticket must be FORWARDABLE");
|
||||
}
|
||||
return creds;
|
||||
}
|
||||
|
||||
|
||||
@ -316,11 +316,12 @@ void initializeISA
|
||||
if (isaCls == 0) {
|
||||
jclass c = (*env)->FindClass(env, "java/net/InetSocketAddress");
|
||||
CHECK_NULL(c);
|
||||
isaCtrID = (*env)->GetMethodID(env, c, "<init>",
|
||||
"(Ljava/net/InetAddress;I)V");
|
||||
CHECK_NULL(isaCtrID);
|
||||
isaCls = (*env)->NewGlobalRef(env, c);
|
||||
CHECK_NULL(isaCls);
|
||||
(*env)->DeleteLocalRef(env, c);
|
||||
isaCtrID = (*env)->GetMethodID(env, isaCls, "<init>",
|
||||
"(Ljava/net/InetAddress;I)V");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -128,9 +128,6 @@ java/lang/ClassLoader/deadlock/GetResource.java generic-all
|
||||
|
||||
# jdk_instrument
|
||||
|
||||
# 8058536
|
||||
java/lang/instrument/NativeMethodPrefixAgent.java generic-all
|
||||
|
||||
# 8061177
|
||||
java/lang/instrument/RedefineBigClass.sh generic-all
|
||||
java/lang/instrument/RetransformBigClass.sh generic-all
|
||||
@ -246,6 +243,9 @@ sun/security/tools/keytool/standard.sh solaris-all
|
||||
# 8062758
|
||||
java/security/Security/ClassLoaderDeadlock/Deadlock2.sh generic-all
|
||||
|
||||
# 8026393
|
||||
sun/security/tools/jarsigner/warnings/BadKeyUsageTest.java generic-all
|
||||
|
||||
############################################################################
|
||||
|
||||
# jdk_sound
|
||||
|
||||
@ -628,7 +628,6 @@ needs_compact2 = \
|
||||
sun/net/www/protocol/http \
|
||||
java/io/BufferedReader/Lines.java \
|
||||
java/lang/reflect/DefaultStaticTest/DefaultStaticInvokeTest.java \
|
||||
java/lang/CharSequence/DefaultTest.java \
|
||||
java/lang/IntegralPrimitiveToString.java \
|
||||
java/lang/PrimitiveSumMinMaxTest.java \
|
||||
java/lang/String/StringJoinTest.java \
|
||||
|
||||
@ -50,8 +50,9 @@ public class SubclassGC {
|
||||
}
|
||||
|
||||
ClassLoader systemLoader = ClassLoader.getSystemClassLoader();
|
||||
ClassLoader loader = new URLClassLoader(((URLClassLoader) systemLoader).getURLs(),
|
||||
systemLoader.getParent());
|
||||
URL testClassesURL = new File(System.getProperty("test.classes")).toURI().toURL();
|
||||
ClassLoader loader = new URLClassLoader(new URL[] { testClassesURL } ,
|
||||
systemLoader.getParent());
|
||||
Class<? extends ObjectOutputStream> cl =
|
||||
Class.forName(SubclassOfOOS.class.getName(), false,
|
||||
loader).asSubclass(ObjectOutputStream.class);
|
||||
|
||||
@ -2,5 +2,7 @@
|
||||
grant {
|
||||
permission java.lang.RuntimePermission "createClassLoader";
|
||||
permission java.lang.RuntimePermission "getClassLoader";
|
||||
permission java.util.PropertyPermission "test.classes", "read";
|
||||
permission java.io.FilePermission "<<ALL FILES>>", "read";
|
||||
};
|
||||
|
||||
|
||||
@ -1,101 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.PrimitiveIterator;
|
||||
import java.util.Spliterator;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import static org.testng.Assert.*;
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Unit test for CharSequence default methods
|
||||
* @bug 8012665 8025002
|
||||
* @run testng DefaultTest
|
||||
*/
|
||||
|
||||
@Test(groups = "lib")
|
||||
public class DefaultTest {
|
||||
|
||||
@Test(expectedExceptions = NoSuchElementException.class)
|
||||
public void testEmptyChars() {
|
||||
PrimitiveIterator.OfInt s = "".chars().iterator();
|
||||
assertFalse(s.hasNext());
|
||||
int ch = s.nextInt();
|
||||
}
|
||||
|
||||
public void testSimpleChars() {
|
||||
List<Integer> list = "abc".chars().boxed().collect(Collectors.toList());
|
||||
assertEquals(list, Arrays.asList((int) 'a', (int) 'b', (int) 'c'));
|
||||
}
|
||||
|
||||
public void testCodePointsCharacteristics() {
|
||||
Spliterator.OfInt s = "".codePoints().spliterator();
|
||||
assertFalse(s.hasCharacteristics(Spliterator.SIZED | Spliterator.SUBSIZED));
|
||||
assertTrue(s.hasCharacteristics(Spliterator.ORDERED));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NoSuchElementException.class)
|
||||
public void testEmptyCodePoints() {
|
||||
PrimitiveIterator.OfInt s = "".codePoints().iterator();
|
||||
assertFalse(s.hasNext());
|
||||
int cp = s.nextInt();
|
||||
}
|
||||
|
||||
public void testSimpleCodePoints() {
|
||||
List<Integer> list = "abc".codePoints().boxed().collect(Collectors.toList());
|
||||
assertEquals(list, Arrays.asList((int)'a', (int)'b', (int)'c'));
|
||||
}
|
||||
|
||||
public void testUndefCodePoints() {
|
||||
List<Integer> list = "X\ufffeY".codePoints().boxed().collect(Collectors.toList());
|
||||
assertEquals(list, Arrays.asList((int)'X', 0xFFFE, (int)'Y'));
|
||||
}
|
||||
|
||||
public void testSurrogatePairing() {
|
||||
// U+1D11E = MUSICAL SYMBOL G CLEF
|
||||
// equivalent to surrogate pair U+D834 U+DD1E
|
||||
List<Integer> list;
|
||||
final int GCLEF = 0x1d11e;
|
||||
|
||||
list = "\ud834\udd1e".codePoints().boxed().collect(Collectors.toList());
|
||||
assertEquals(list, Arrays.asList(GCLEF));
|
||||
list = "A\ud834\udd1e".codePoints().boxed().collect(Collectors.toList());
|
||||
assertEquals(list, Arrays.asList((int)'A', GCLEF));
|
||||
list = "\ud834\udd1eB".codePoints().boxed().collect(Collectors.toList());
|
||||
assertEquals(list, Arrays.asList(GCLEF, (int)'B'));
|
||||
list = "X\ud834\udd1eY".codePoints().boxed().collect(Collectors.toList());
|
||||
assertEquals(list, Arrays.asList((int)'X', GCLEF, (int)'Y'));
|
||||
}
|
||||
|
||||
public void testUndefUnpaired() {
|
||||
List<Integer> list = "W\udd1eX\ud834Y\ufffeZ".codePoints().boxed().collect(Collectors.toList());
|
||||
assertEquals(list, Arrays.asList(
|
||||
(int)'W', 0xdd1e, (int)'X', 0xd834, (int)'Y', 0xfffe, (int)'Z'));
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2015, 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 @@
|
||||
* @bug 4199068 4738465 4937983 4930681 4926230 4931433 4932663 4986689
|
||||
* 5026830 5023243 5070673 4052517 4811767 6192449 6397034 6413313
|
||||
* 6464154 6523983 6206031 4960438 6631352 6631966 6850957 6850958
|
||||
* 4947220 7018606 7034570 4244896 5049299 8003488
|
||||
* 4947220 7018606 7034570 4244896 5049299 8003488 8054494
|
||||
* @summary Basic tests for Process and Environment Variable code
|
||||
* @run main/othervm/timeout=300 Basic
|
||||
* @run main/othervm/timeout=300 -Djdk.lang.Process.launchMechanism=fork Basic
|
||||
@ -2042,7 +2042,7 @@ public class Basic {
|
||||
final Object deferred;
|
||||
Class<?> c = s.getClass();
|
||||
if (c.getName().equals(
|
||||
"java.lang.UNIXProcess$DeferredCloseInputStream"))
|
||||
"java.lang.ProcessImpl$DeferredCloseInputStream"))
|
||||
{
|
||||
deferred = s;
|
||||
} else {
|
||||
@ -2059,13 +2059,11 @@ public class Basic {
|
||||
Thread.yield();
|
||||
}
|
||||
} else if (s instanceof BufferedInputStream) {
|
||||
Field f = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
f.setAccessible(true);
|
||||
Unsafe unsafe = (Unsafe)f.get(null);
|
||||
|
||||
while (unsafe.tryMonitorEnter(s)) {
|
||||
unsafe.monitorExit(s);
|
||||
Thread.sleep(1);
|
||||
// Wait until after the s.read occurs in "thread" by
|
||||
// checking when the input stream monitor is acquired
|
||||
// (BufferedInputStream.read is synchronized)
|
||||
while (!isLocked(s, 10)) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
}
|
||||
p.destroy();
|
||||
@ -2565,4 +2563,21 @@ public class Basic {
|
||||
catch (Throwable t) {
|
||||
if (k.isAssignableFrom(t.getClass())) pass();
|
||||
else unexpected(t);}}
|
||||
|
||||
static boolean isLocked(final Object monitor, final long millis) throws InterruptedException {
|
||||
return new Thread() {
|
||||
volatile boolean unlocked;
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
synchronized (monitor) { unlocked = true; }
|
||||
}
|
||||
|
||||
boolean isLocked() throws InterruptedException {
|
||||
start();
|
||||
join(millis);
|
||||
return !unlocked;
|
||||
}
|
||||
}.isLocked();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2014, 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
|
||||
@ -25,7 +25,7 @@
|
||||
* @test
|
||||
* @bug 7038914 8016341
|
||||
* @summary Verify that the reference handler does not die after an OOME allocating the InterruptedException object
|
||||
* @run main/othervm -Xmx24M -XX:-UseTLAB OOMEInReferenceHandler
|
||||
* @run main/othervm -XX:-UseGCOverheadLimit -Xmx24M -XX:-UseTLAB OOMEInReferenceHandler
|
||||
* @author peter.levart@gmail.com
|
||||
*/
|
||||
|
||||
|
||||
147
jdk/test/java/net/ServerSocket/AcceptInheritHandle.java
Normal file
147
jdk/test/java/net/ServerSocket/AcceptInheritHandle.java
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8067105
|
||||
* @summary Socket returned by ServerSocket.accept() is inherited by child process on Windows
|
||||
* @author Chris Hegarty
|
||||
*/
|
||||
|
||||
import java.io.*;
|
||||
import java.net.*;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public class AcceptInheritHandle {
|
||||
|
||||
enum ServerSocketProducer {
|
||||
JAVA_NET(() -> {
|
||||
try {
|
||||
return new ServerSocket(); }
|
||||
catch(IOException x) {
|
||||
throw new UncheckedIOException(x);
|
||||
}
|
||||
}),
|
||||
NIO_CHANNELS(() -> {
|
||||
try {
|
||||
return ServerSocketChannel.open().socket();
|
||||
} catch (IOException x) {
|
||||
throw new UncheckedIOException(x);
|
||||
}
|
||||
});
|
||||
|
||||
final Supplier<ServerSocket> supplier;
|
||||
ServerSocketProducer(Supplier<ServerSocket> supplier) {
|
||||
this.supplier = supplier;
|
||||
}
|
||||
Supplier<ServerSocket> supplier () { return supplier; }
|
||||
}
|
||||
|
||||
static final String JAVA = System.getProperty("java.home")
|
||||
+ File.separator + "bin" + File.separator + "java";
|
||||
|
||||
static final String CLASSPATH = System.getProperty("java.class.path");
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
if (args.length == 1)
|
||||
server(ServerSocketProducer.valueOf(args[0]));
|
||||
else
|
||||
mainEntry();
|
||||
}
|
||||
|
||||
static void mainEntry() throws Exception {
|
||||
testJavaNetServerSocket();
|
||||
testNioServerSocketChannel();
|
||||
}
|
||||
|
||||
static void testJavaNetServerSocket() throws Exception {
|
||||
test(ServerSocketProducer.JAVA_NET);
|
||||
test(ServerSocketProducer.JAVA_NET, "-Djava.net.preferIPv4Stack=true");
|
||||
}
|
||||
static void testNioServerSocketChannel() throws Exception {
|
||||
test(ServerSocketProducer.NIO_CHANNELS);
|
||||
}
|
||||
|
||||
static void test(ServerSocketProducer ssp, String... sysProps) throws Exception {
|
||||
System.out.println("\nStarting test for " + ssp.name());
|
||||
|
||||
List<String> commands = new ArrayList<>();
|
||||
commands.add(JAVA);
|
||||
for (String prop : sysProps)
|
||||
commands.add(prop);
|
||||
commands.add("-cp");
|
||||
commands.add(CLASSPATH);
|
||||
commands.add("AcceptInheritHandle");
|
||||
commands.add(ssp.name());
|
||||
|
||||
System.out.println("Executing: "+ commands);
|
||||
ProcessBuilder pb = new ProcessBuilder(commands);
|
||||
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
Process serverProcess = pb.start();
|
||||
DataInputStream dis = new DataInputStream(serverProcess.getInputStream());
|
||||
|
||||
int port = dis.readInt();
|
||||
System.out.println("Server process listening on " + port + ", connecting...");
|
||||
|
||||
Socket socket = new Socket("localhost", port);
|
||||
String s = dis.readUTF();
|
||||
System.out.println("Server process said " + s);
|
||||
|
||||
serverProcess.destroy();
|
||||
serverProcess.waitFor(30, TimeUnit.SECONDS);
|
||||
System.out.println("serverProcess exitCode:" + serverProcess.exitValue());
|
||||
|
||||
try {
|
||||
socket.setSoTimeout(10 * 1000);
|
||||
socket.getInputStream().read();
|
||||
} catch (SocketTimeoutException x) {
|
||||
// failed
|
||||
throw new RuntimeException("Failed: should get reset, not " + x);
|
||||
} catch (SocketException x) {
|
||||
System.out.println("Expected:" + x);
|
||||
}
|
||||
}
|
||||
|
||||
static void server(ServerSocketProducer producer) throws Exception {
|
||||
try (ServerSocket ss = producer.supplier().get()) {
|
||||
ss.bind(new InetSocketAddress(0));
|
||||
int port = ss.getLocalPort();
|
||||
DataOutputStream dos = new DataOutputStream(System.out);
|
||||
dos.writeInt(port);
|
||||
dos.flush();
|
||||
|
||||
ss.accept(); // do not close
|
||||
|
||||
Runtime.getRuntime().exec("sleep 20");
|
||||
Thread.sleep(3 * 1000);
|
||||
|
||||
dos.writeUTF("kill me!");
|
||||
dos.flush();
|
||||
Thread.sleep(30 * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 4106601 8026245
|
||||
* @bug 4106601 8026245 8071424
|
||||
* @run main/othervm GetLocalAddress
|
||||
* @run main/othervm -Djava.net.preferIPv4Stack=true GetLocalAddress
|
||||
* @run main/othervm -Djava.net.preferIPv6Addresses=true GetLocalAddress
|
||||
@ -39,6 +39,8 @@ public class GetLocalAddress implements Runnable {
|
||||
static int port;
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
testBindNull();
|
||||
|
||||
boolean error = true;
|
||||
int linger = 65546;
|
||||
int value = 0;
|
||||
@ -66,4 +68,18 @@ public class GetLocalAddress implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
static void testBindNull() throws Exception {
|
||||
try (Socket soc = new Socket()) {
|
||||
soc.bind(null);
|
||||
if (!soc.isBound())
|
||||
throw new RuntimeException(
|
||||
"should be bound after bind(null)");
|
||||
if (soc.getLocalPort() <= 0)
|
||||
throw new RuntimeException(
|
||||
"bind(null) failed, local port: " + soc.getLocalPort());
|
||||
if (soc.getLocalAddress() == null)
|
||||
throw new RuntimeException(
|
||||
"bind(null) failed, local address is null");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,107 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @bug 6287579
|
||||
* @summary Make sure that getContents() of ListResourceBundle subclasses is 'protected'
|
||||
* and returns a different Object[]][] instance in each invocation.
|
||||
*/
|
||||
|
||||
import java.lang.reflect.*;
|
||||
import java.util.*;
|
||||
|
||||
public class Bug6287579 {
|
||||
static final Locale ROOT = new Locale("");
|
||||
|
||||
static final String[] baseNames = {
|
||||
"sun.text.resources.BreakIteratorInfo",
|
||||
"sun.text.resources.FormatData",
|
||||
"sun.text.resources.CollationData",
|
||||
"sun.util.resources.LocaleNames",
|
||||
"sun.util.resources.TimeZoneNames",
|
||||
|
||||
// Make sure the properties-to-class conversion tool generates
|
||||
// the proper getContents().
|
||||
"sun.awt.resources.awt",
|
||||
};
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
int errors = 0;
|
||||
|
||||
List<Locale> locales = new ArrayList<Locale>();
|
||||
locales.addAll(Arrays.asList(Locale.getAvailableLocales()));
|
||||
locales.add(ROOT);
|
||||
|
||||
for (Locale locale : locales) {
|
||||
for (String base : baseNames) {
|
||||
String className = getResourceName(base, locale);
|
||||
errors += checkGetContents(className);
|
||||
}
|
||||
}
|
||||
if (errors > 0) {
|
||||
throw new RuntimeException(errors + " errors found");
|
||||
}
|
||||
}
|
||||
|
||||
static int checkGetContents(String className) throws Exception {
|
||||
int err = 0;
|
||||
try {
|
||||
Class clazz = Class.forName(className);
|
||||
Method getContentsMethod = clazz.getDeclaredMethod("getContents",
|
||||
(Class[]) null);
|
||||
if (!Modifier.isProtected(getContentsMethod.getModifiers())) {
|
||||
System.err.println(className + ": not protected");
|
||||
err++;
|
||||
}
|
||||
getContentsMethod.setAccessible(true);
|
||||
Object bundle = clazz.newInstance();
|
||||
Object o1 = getContentsMethod.invoke(bundle, (Object[]) null);
|
||||
Object o2 = getContentsMethod.invoke(bundle, (Object[]) null);
|
||||
if (o1 == o2) {
|
||||
System.err.println(className + ": same instance returned");
|
||||
err++;
|
||||
}
|
||||
} catch (ClassNotFoundException ce) {
|
||||
// Skip nonexistent classes
|
||||
} catch (NoSuchMethodException me) {
|
||||
System.out.println(className + ": no declared getContents()");
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
static String getResourceName(String base, Locale locale) {
|
||||
if (locale.equals(ROOT)) {
|
||||
return base;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder(base);
|
||||
sb.append('_').append(locale.getLanguage());
|
||||
if (locale.getCountry().length() > 0
|
||||
|| locale.getVariant().length() > 0) {
|
||||
sb.append('_').append(locale.getCountry());
|
||||
}
|
||||
if (locale.getVariant().length() > 0) {
|
||||
sb.append('_').append(locale.getVariant());
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2015, 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,7 +23,7 @@
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8020156 8020009 8022326 8012913 8024405 8024408
|
||||
* @bug 8020156 8020009 8022326 8012913 8024405 8024408 8071477
|
||||
* @run testng SpliteratorCharacteristics
|
||||
*/
|
||||
|
||||
@ -59,6 +59,57 @@ import static org.testng.Assert.*;
|
||||
@Test
|
||||
public class SpliteratorCharacteristics {
|
||||
|
||||
public void testSpliteratorFromCharSequence() {
|
||||
class CharSequenceImpl implements CharSequence {
|
||||
final String s;
|
||||
|
||||
public CharSequenceImpl(String s) {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return s.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return s.charAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(int start, int end) {
|
||||
return s.subSequence(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
CharSequence cs = "A";
|
||||
Spliterator.OfInt s = cs.chars().spliterator();
|
||||
assertCharacteristics(s, Spliterator.IMMUTABLE | Spliterator.ORDERED |
|
||||
Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
s = cs.codePoints().spliterator();
|
||||
assertCharacteristics(s, Spliterator.IMMUTABLE | Spliterator.ORDERED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
|
||||
for (CharSequence c : Arrays.asList(new CharSequenceImpl("A"),
|
||||
new StringBuilder("A"),
|
||||
new StringBuffer("A"))) {
|
||||
s = cs.chars().spliterator();
|
||||
assertCharacteristics(s, Spliterator.ORDERED |
|
||||
Spliterator.SIZED | Spliterator.SUBSIZED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
s = cs.codePoints().spliterator();
|
||||
assertCharacteristics(s, Spliterator.ORDERED);
|
||||
assertHasNotCharacteristics(s, Spliterator.CONCURRENT);
|
||||
}
|
||||
}
|
||||
|
||||
public void testSpliteratorFromCollection() {
|
||||
List<Integer> l = Arrays.asList(1, 2, 3, 4);
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2015, 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
|
||||
@ -25,7 +25,7 @@
|
||||
* @test
|
||||
* @summary Spliterator traversing and splitting tests
|
||||
* @run testng SpliteratorTraversingAndSplittingTest
|
||||
* @bug 8020016
|
||||
* @bug 8020016 8071477
|
||||
*/
|
||||
|
||||
import org.testng.annotations.DataProvider;
|
||||
@ -85,7 +85,38 @@ import static org.testng.Assert.assertEquals;
|
||||
@Test
|
||||
public class SpliteratorTraversingAndSplittingTest {
|
||||
|
||||
private static List<Integer> SIZES = Arrays.asList(0, 1, 10, 100, 1000);
|
||||
private static final List<Integer> SIZES = Arrays.asList(0, 1, 10, 100, 1000);
|
||||
|
||||
private static final String LOW = new String(new char[] {Character.MIN_LOW_SURROGATE});
|
||||
private static final String HIGH = new String(new char[] {Character.MIN_HIGH_SURROGATE});
|
||||
private static final String HIGH_LOW = HIGH + LOW;
|
||||
private static final String CHAR_HIGH_LOW = "A" + HIGH_LOW;
|
||||
private static final String HIGH_LOW_CHAR = HIGH_LOW + "A";
|
||||
private static final String CHAR_HIGH_LOW_CHAR = "A" + HIGH_LOW + "A";
|
||||
|
||||
private static final List<String> STRINGS = generateTestStrings();
|
||||
|
||||
private static List<String> generateTestStrings() {
|
||||
List<String> strings = new ArrayList<>();
|
||||
for (int n : Arrays.asList(1, 2, 3, 16, 17)) {
|
||||
strings.add(generate("A", n));
|
||||
strings.add(generate(LOW, n));
|
||||
strings.add(generate(HIGH, n));
|
||||
strings.add(generate(HIGH_LOW, n));
|
||||
strings.add(generate(CHAR_HIGH_LOW, n));
|
||||
strings.add(generate(HIGH_LOW_CHAR, n));
|
||||
strings.add(generate(CHAR_HIGH_LOW_CHAR, n));
|
||||
}
|
||||
return strings;
|
||||
}
|
||||
|
||||
private static String generate(String s, int n) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < n; i++) {
|
||||
sb.append(s);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private static class SpliteratorDataBuilder<T> {
|
||||
List<Object[]> data;
|
||||
@ -564,6 +595,60 @@ public class SpliteratorTraversingAndSplittingTest {
|
||||
}
|
||||
}
|
||||
|
||||
private static class SpliteratorOfIntCharDataBuilder {
|
||||
List<Object[]> data;
|
||||
|
||||
String s;
|
||||
|
||||
List<Integer> expChars;
|
||||
|
||||
List<Integer> expCodePoints;
|
||||
|
||||
SpliteratorOfIntCharDataBuilder(List<Object[]> data, String s) {
|
||||
this.data = data;
|
||||
this.s = s;
|
||||
this.expChars = transform(s, false);
|
||||
this.expCodePoints = transform(s, true);
|
||||
}
|
||||
|
||||
static List<Integer> transform(String s, boolean toCodePoints) {
|
||||
List<Integer> l = new ArrayList<>();
|
||||
|
||||
if (!toCodePoints) {
|
||||
for (int i = 0; i < s.length(); i++) {
|
||||
l.add((int) s.charAt(i));
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (int i = 0; i < s.length();) {
|
||||
char c1 = s.charAt(i++);
|
||||
int cp = c1;
|
||||
if (Character.isHighSurrogate(c1) && i < s.length()) {
|
||||
char c2 = s.charAt(i);
|
||||
if (Character.isLowSurrogate(c2)) {
|
||||
i++;
|
||||
cp = Character.toCodePoint(c1, c2);
|
||||
}
|
||||
}
|
||||
l.add(cp);
|
||||
}
|
||||
}
|
||||
return l;
|
||||
}
|
||||
|
||||
void add(String description, Function<String, CharSequence> f) {
|
||||
description = description.replace("%s", s);
|
||||
{
|
||||
Supplier<Spliterator.OfInt> supplier = () -> f.apply(s).chars().spliterator();
|
||||
data.add(new Object[]{description + ".chars().spliterator()", expChars, supplier});
|
||||
}
|
||||
{
|
||||
Supplier<Spliterator.OfInt> supplier = () -> f.apply(s).codePoints().spliterator();
|
||||
data.add(new Object[]{description + ".codePoints().spliterator()", expCodePoints, supplier});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static Object[][] spliteratorOfIntDataProvider;
|
||||
|
||||
@DataProvider(name = "Spliterator.OfInt")
|
||||
@ -615,6 +700,43 @@ public class SpliteratorTraversingAndSplittingTest {
|
||||
() -> new IntSpliteratorFromArray(exp));
|
||||
}
|
||||
|
||||
// Class for testing default methods
|
||||
class CharSequenceImpl implements CharSequence {
|
||||
final String s;
|
||||
|
||||
public CharSequenceImpl(String s) {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return s.length();
|
||||
}
|
||||
|
||||
@Override
|
||||
public char charAt(int index) {
|
||||
return s.charAt(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CharSequence subSequence(int start, int end) {
|
||||
return s.subSequence(start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
for (String string : STRINGS) {
|
||||
SpliteratorOfIntCharDataBuilder cdb = new SpliteratorOfIntCharDataBuilder(data, string);
|
||||
cdb.add("\"%s\"", s -> s);
|
||||
cdb.add("new CharSequenceImpl(\"%s\")", CharSequenceImpl::new);
|
||||
cdb.add("new StringBuilder(\"%s\")", StringBuilder::new);
|
||||
cdb.add("new StringBuffer(\"%s\")", StringBuffer::new);
|
||||
}
|
||||
|
||||
return spliteratorOfIntDataProvider = data.toArray(new Object[0][]);
|
||||
}
|
||||
|
||||
|
||||
104
jdk/test/javax/xml/jaxp/transform/8062923/XslSubstringTest.java
Normal file
104
jdk/test/javax/xml/jaxp/transform/8062923/XslSubstringTest.java
Normal file
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8062923 8062924
|
||||
* @run testng XslSubstringTest
|
||||
* @summary Test xsl substring function with negative, Inf and
|
||||
* NaN length and few other use cases
|
||||
*/
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.stream.StreamResult;
|
||||
import javax.xml.transform.stream.StreamSource;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
public class XslSubstringTest {
|
||||
|
||||
final String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><test></test>";
|
||||
final String xslPre = "<xsl:stylesheet version='1.0'"
|
||||
+ " xmlns:xsl='http://www.w3.org/1999/XSL/Transform'>"
|
||||
+ "<xsl:output method='xml' indent='yes' omit-xml-declaration='yes'/>"
|
||||
+ "<xsl:template match='/'><t>";
|
||||
final String xslPost = "</t></xsl:template></xsl:stylesheet>";
|
||||
|
||||
private String testTransform(String xsl) throws Exception {
|
||||
//Prepare sources for transormation
|
||||
Source src = new StreamSource(new StringReader(xml));
|
||||
Source xslsrc = new StreamSource(new StringReader(xslPre + xsl + xslPost));
|
||||
//Create factory, template and transformer
|
||||
TransformerFactory tf = TransformerFactory.newInstance();
|
||||
Templates tmpl = tf.newTemplates(xslsrc);
|
||||
Transformer t = tmpl.newTransformer();
|
||||
//Prepare output stream
|
||||
StringWriter xmlResultString = new StringWriter();
|
||||
StreamResult xmlResultStream = new StreamResult(xmlResultString);
|
||||
//Transform
|
||||
t.transform(src, xmlResultStream);
|
||||
return xmlResultString.toString().trim();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test8062923() throws Exception {
|
||||
assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2,-1)\"/>|"),
|
||||
"<t>||</t>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test8062924() throws Exception {
|
||||
assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2,-1 div 0)\"/>|"),
|
||||
"<t>||</t>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneral1() throws Exception {
|
||||
assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, 1)\"/>|"),
|
||||
"<t>|s|</t>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneral2() throws Exception {
|
||||
assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, 1 div 0)\"/>|"),
|
||||
"<t>|sdf|</t>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneral3() throws Exception {
|
||||
assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, -0 div 0)\"/>|"),
|
||||
"<t>||</t>");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneral4() throws Exception {
|
||||
assertEquals(testTransform("|<xsl:value-of select=\"substring('asdf',2, 0 div 0)\"/>|"),
|
||||
"<t>||</t>");
|
||||
}
|
||||
}
|
||||
134
jdk/test/javax/xml/ws/8046817/GenerateEnumSchema.java
Normal file
134
jdk/test/javax/xml/ws/8046817/GenerateEnumSchema.java
Normal file
@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8046817
|
||||
* @summary schemagen fails to generate xsd for enum types
|
||||
* @run main/othervm GenerateEnumSchema
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Scanner;
|
||||
|
||||
public class GenerateEnumSchema {
|
||||
|
||||
private static final String SCHEMA_OUTPUT_FILENAME = "schema1.xsd";
|
||||
private static final File schemaOutputFile = new File(SCHEMA_OUTPUT_FILENAME);
|
||||
|
||||
public static void main(String[] args) throws Exception, IOException {
|
||||
//Check schema generation for class type
|
||||
runSchemaGen("TestClassType.java");
|
||||
checkIfSchemaGenerated();
|
||||
checkSchemaContent("<xs:complexType name=\"testClassType\">");
|
||||
checkSchemaContent("<xs:element name=\"a\" type=\"xs:int\"/>");
|
||||
schemaOutputFile.delete();
|
||||
//Check schema generation for enum type
|
||||
runSchemaGen("TestEnumType.java");
|
||||
checkIfSchemaGenerated();
|
||||
checkSchemaContent("<xs:simpleType name=\"testEnumType\">");
|
||||
checkSchemaContent("<xs:enumeration value=\"ONE\"/>");
|
||||
checkSchemaContent("<xs:enumeration value=\"TWO\"/>");
|
||||
checkSchemaContent("<xs:enumeration value=\"THREE\"/>");
|
||||
schemaOutputFile.delete();
|
||||
}
|
||||
|
||||
private static void checkIfSchemaGenerated() {
|
||||
if (!schemaOutputFile.exists()) {
|
||||
throw new RuntimeException("FAIL:" + SCHEMA_OUTPUT_FILENAME + " was not generated by schemagen tool");
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkSchemaContent(String exp_token) throws FileNotFoundException {
|
||||
System.out.print("Check if generated schema contains '" + exp_token + "' string: ");
|
||||
try (Scanner scanner = new Scanner(schemaOutputFile)) {
|
||||
if (scanner.findWithinHorizon(exp_token, 0) != null) {
|
||||
System.out.println("OK");
|
||||
return;
|
||||
}
|
||||
}
|
||||
System.out.println("FAIL");
|
||||
throw new RuntimeException("The '" + exp_token + "' is not found in generated schema");
|
||||
|
||||
}
|
||||
|
||||
private static String getClassFilePath(String filename) {
|
||||
String testSrc = System.getProperty("test.src");
|
||||
if (testSrc == null) {
|
||||
testSrc = ".";
|
||||
}
|
||||
return Paths.get(testSrc).resolve(filename).toString();
|
||||
}
|
||||
|
||||
private static String getSchemagen() {
|
||||
String javaHome = System.getProperty("java.home");
|
||||
if (javaHome.endsWith("jre")) {
|
||||
javaHome = new File(javaHome).getParent();
|
||||
}
|
||||
String schemagen = javaHome + File.separator + "bin" + File.separator + "schemagen";
|
||||
if (System.getProperty("os.name").startsWith("Windows")) {
|
||||
schemagen = schemagen.concat(".exe");
|
||||
}
|
||||
return schemagen;
|
||||
}
|
||||
|
||||
private static void logOutput(Process p) throws IOException {
|
||||
BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
|
||||
String s = r.readLine();
|
||||
while (s != null) {
|
||||
System.out.println(s.trim());
|
||||
s = r.readLine();
|
||||
}
|
||||
}
|
||||
|
||||
private static void runSchemaGen(String classFile) {
|
||||
String schemagen = getSchemagen();
|
||||
|
||||
try {
|
||||
System.out.println("Call to schemagen: " + schemagen + " " + classFile);
|
||||
String[] schemagen_args = {
|
||||
schemagen,
|
||||
getClassFilePath(classFile)
|
||||
};
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(schemagen_args);
|
||||
pb.redirectErrorStream(true);
|
||||
Process p = pb.start();
|
||||
logOutput(p);
|
||||
int result = p.waitFor();
|
||||
p.destroy();
|
||||
|
||||
if (result != 0) {
|
||||
throw new RuntimeException("schemagen failed");
|
||||
}
|
||||
} catch (IOException | InterruptedException e) {
|
||||
System.err.println("Can't run schemagen tool. Exception:");
|
||||
e.printStackTrace(System.err);
|
||||
throw new RuntimeException("Error launching schemagen tool");
|
||||
}
|
||||
}
|
||||
}
|
||||
29
jdk/test/javax/xml/ws/8046817/TestClassType.java
Normal file
29
jdk/test/javax/xml/ws/8046817/TestClassType.java
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
|
||||
@XmlType
|
||||
public class TestClassType {
|
||||
public int a;
|
||||
}
|
||||
29
jdk/test/javax/xml/ws/8046817/TestEnumType.java
Normal file
29
jdk/test/javax/xml/ws/8046817/TestEnumType.java
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import javax.xml.bind.annotation.XmlEnum;
|
||||
|
||||
@XmlEnum(String.class)
|
||||
public enum TestEnumType {
|
||||
ONE, TWO, THREE
|
||||
}
|
||||
119
jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java
Normal file
119
jdk/test/lib/testlibrary/jdk/testlibrary/JarUtils.java
Normal file
@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package jdk.testlibrary;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.jar.Manifest;
|
||||
|
||||
/**
|
||||
* Common library for various test jar file utility functions.
|
||||
*/
|
||||
public final class JarUtils {
|
||||
|
||||
/**
|
||||
* Create jar file with specified files.
|
||||
*/
|
||||
public static void createJar(String dest, String... files)
|
||||
throws IOException {
|
||||
try (JarOutputStream jos = new JarOutputStream(
|
||||
new FileOutputStream(dest), new Manifest())) {
|
||||
for (String file : files) {
|
||||
System.out.println(String.format("Adding %s to %s",
|
||||
file, dest));
|
||||
|
||||
// add an archive entry, and write a file
|
||||
jos.putNextEntry(new JarEntry(file));
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
fis.transferTo(jos);
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add specified files to existing jar file.
|
||||
*/
|
||||
public static void updateJar(String src, String dest, String... files)
|
||||
throws IOException {
|
||||
try (JarOutputStream jos = new JarOutputStream(
|
||||
new FileOutputStream(dest))) {
|
||||
|
||||
// copy each old entry into destination unless the entry name
|
||||
// is in the updated list
|
||||
List<String> updatedFiles = new ArrayList<>();
|
||||
try (JarFile srcJarFile = new JarFile(src)) {
|
||||
Enumeration entries = srcJarFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
JarEntry entry = (JarEntry) entries.nextElement();
|
||||
String name = entry.getName();
|
||||
boolean found = false;
|
||||
for (String file : files) {
|
||||
if (name.equals(file)) {
|
||||
updatedFiles.add(file);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (found) {
|
||||
System.out.println(String.format("Updating %s with %s",
|
||||
dest, name));
|
||||
jos.putNextEntry(new JarEntry(name));
|
||||
try (FileInputStream fis = new FileInputStream(name)) {
|
||||
fis.transferTo(jos);
|
||||
}
|
||||
} else {
|
||||
System.out.println(String.format("Copying %s to %s",
|
||||
name, dest));
|
||||
jos.putNextEntry(entry);
|
||||
srcJarFile.getInputStream(entry).transferTo(jos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// append new files
|
||||
for (String file : files) {
|
||||
if (!updatedFiles.contains(file)) {
|
||||
System.out.println(String.format("Adding %s with %s",
|
||||
dest, file));
|
||||
jos.putNextEntry(new JarEntry(file));
|
||||
try (FileInputStream fis = new FileInputStream(file)) {
|
||||
fis.transferTo(jos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2013, 2015, 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
|
||||
@ -30,6 +30,7 @@ import java.lang.management.RuntimeMXBean;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.Map;
|
||||
@ -378,4 +379,40 @@ public final class ProcessTools {
|
||||
}
|
||||
return cmd.toString().trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a process, waits for it to finish, prints the process output
|
||||
* to stdout, and returns the process output.
|
||||
*
|
||||
* The process will have exited before this method returns.
|
||||
*
|
||||
* @param cmds The command line to execute.
|
||||
* @return The {@linkplain OutputAnalyzer} instance wrapping the process.
|
||||
*/
|
||||
public static OutputAnalyzer executeCommand(String... cmds)
|
||||
throws Throwable {
|
||||
String cmdLine = Arrays.stream(cmds).collect(Collectors.joining(" "));
|
||||
System.out.println("Command line: [" + cmdLine + "]");
|
||||
OutputAnalyzer analyzer = ProcessTools.executeProcess(cmds);
|
||||
System.out.println(analyzer.getOutput());
|
||||
return analyzer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes a process, waits for it to finish, prints the process output
|
||||
* to stdout and returns the process output.
|
||||
*
|
||||
* The process will have exited before this method returns.
|
||||
*
|
||||
* @param pb The ProcessBuilder to execute.
|
||||
* @return The {@linkplain OutputAnalyzer} instance wrapping the process.
|
||||
*/
|
||||
public static OutputAnalyzer executeCommand(ProcessBuilder pb)
|
||||
throws Throwable {
|
||||
String cmdLine = pb.command().stream().collect(Collectors.joining(" "));
|
||||
System.out.println("Command line: [" + cmdLine + "]");
|
||||
OutputAnalyzer analyzer = ProcessTools.executeProcess(pb);
|
||||
System.out.println(analyzer.getOutput());
|
||||
return analyzer;
|
||||
}
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
|
||||
import com.sun.security.auth.module.Krb5LoginModule;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
@ -584,7 +585,12 @@ public class Context {
|
||||
out.name = name + " as " + out.cred.getName().toString();
|
||||
return out;
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw pae.getException();
|
||||
Exception e = pae.getException();
|
||||
if (e instanceof InvocationTargetException) {
|
||||
throw (Exception)((InvocationTargetException) e).getTargetException();
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
81
jdk/test/sun/security/krb5/auto/ForwardableCheck.java
Normal file
81
jdk/test/sun/security/krb5/auto/ForwardableCheck.java
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8022582
|
||||
* @summary Relax response flags checking in sun.security.krb5.KrbKdcRep.check.
|
||||
* @compile -XDignore.symbol.file ForwardableCheck.java
|
||||
* @run main/othervm ForwardableCheck
|
||||
*/
|
||||
|
||||
import org.ietf.jgss.GSSException;
|
||||
import sun.security.jgss.GSSUtil;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class ForwardableCheck {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
OneKDC kdc = new OneKDC(null);
|
||||
kdc.writeJAASConf();
|
||||
|
||||
// USER can impersonate someone else
|
||||
kdc.setOption(KDC.Option.ALLOW_S4U2SELF,
|
||||
Arrays.asList(OneKDC.USER + "@" + OneKDC.REALM));
|
||||
// USER2 is sensitive
|
||||
kdc.setOption(KDC.Option.SENSITIVE_ACCOUNTS,
|
||||
Arrays.asList(OneKDC.USER2 + "@" + OneKDC.REALM));
|
||||
|
||||
Context c;
|
||||
|
||||
// USER2 is sensitive but it's still able to get a normal ticket
|
||||
c = Context.fromUserPass(OneKDC.USER2, OneKDC.PASS2, false);
|
||||
|
||||
// ... and connect to another account
|
||||
c.startAsClient(OneKDC.USER, GSSUtil.GSS_KRB5_MECH_OID);
|
||||
c.x().requestCredDeleg(true);
|
||||
c.x().requestMutualAuth(false);
|
||||
|
||||
c.take(new byte[0]);
|
||||
|
||||
if (!c.x().isEstablished()) {
|
||||
throw new Exception("Context should have been established");
|
||||
}
|
||||
|
||||
// ... but will not be able to delegate itself
|
||||
if (c.x().getCredDelegState()) {
|
||||
throw new Exception("Impossible");
|
||||
}
|
||||
|
||||
// Although USER is allowed to impersonate other people,
|
||||
// it cannot impersonate USER2 coz it's sensitive.
|
||||
c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
|
||||
try {
|
||||
c.impersonate(OneKDC.USER2);
|
||||
throw new Exception("Should fail");
|
||||
} catch (GSSException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -198,6 +198,10 @@ public class KDC {
|
||||
* Krb5.KDC_ERR_POLICY will be send for S4U2proxy request.
|
||||
*/
|
||||
ALLOW_S4U2PROXY,
|
||||
/**
|
||||
* Sensitive accounts can never be delegated.
|
||||
*/
|
||||
SENSITIVE_ACCOUNTS,
|
||||
};
|
||||
|
||||
static {
|
||||
@ -643,7 +647,7 @@ public class KDC {
|
||||
try {
|
||||
System.out.println(realm + "> " + tgsReq.reqBody.cname +
|
||||
" sends TGS-REQ for " +
|
||||
service);
|
||||
service + ", " + tgsReq.reqBody.kdcOptions);
|
||||
KDCReqBody body = tgsReq.reqBody;
|
||||
int[] eTypes = KDCReqBodyDotEType(body);
|
||||
int e2 = eTypes[0]; // etype for outgoing session key
|
||||
@ -719,7 +723,13 @@ public class KDC {
|
||||
boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
|
||||
if (body.kdcOptions.get(KDCOptions.FORWARDABLE)
|
||||
&& allowForwardable) {
|
||||
bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
|
||||
List<String> sensitives = (List<String>)
|
||||
options.get(Option.SENSITIVE_ACCOUNTS);
|
||||
if (sensitives != null && sensitives.contains(cname.toString())) {
|
||||
// Cannot make FORWARDABLE
|
||||
} else {
|
||||
bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
|
||||
}
|
||||
}
|
||||
if (body.kdcOptions.get(KDCOptions.FORWARDED) ||
|
||||
etp.flags.get(Krb5.TKT_OPTS_FORWARDED)) {
|
||||
@ -824,7 +834,8 @@ public class KDC {
|
||||
t,
|
||||
edata);
|
||||
System.out.println(" Return " + tgsRep.cname
|
||||
+ " ticket for " + tgsRep.ticket.sname);
|
||||
+ " ticket for " + tgsRep.ticket.sname + ", flags "
|
||||
+ tFlags);
|
||||
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
out.write(DerValue.createTag(DerValue.TAG_APPLICATION,
|
||||
@ -869,7 +880,7 @@ public class KDC {
|
||||
try {
|
||||
System.out.println(realm + "> " + asReq.reqBody.cname +
|
||||
" sends AS-REQ for " +
|
||||
service);
|
||||
service + ", " + asReq.reqBody.kdcOptions);
|
||||
|
||||
KDCReqBody body = asReq.reqBody;
|
||||
|
||||
@ -926,7 +937,13 @@ public class KDC {
|
||||
//body.from
|
||||
boolean[] bFlags = new boolean[Krb5.TKT_OPTS_MAX+1];
|
||||
if (body.kdcOptions.get(KDCOptions.FORWARDABLE)) {
|
||||
bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
|
||||
List<String> sensitives = (List<String>)
|
||||
options.get(Option.SENSITIVE_ACCOUNTS);
|
||||
if (sensitives != null && sensitives.contains(body.cname.toString())) {
|
||||
// Cannot make FORWARDABLE
|
||||
} else {
|
||||
bFlags[Krb5.TKT_OPTS_FORWARDABLE] = true;
|
||||
}
|
||||
}
|
||||
if (body.kdcOptions.get(KDCOptions.RENEWABLE)) {
|
||||
bFlags[Krb5.TKT_OPTS_RENEWABLE] = true;
|
||||
@ -1102,7 +1119,8 @@ public class KDC {
|
||||
edata);
|
||||
|
||||
System.out.println(" Return " + asRep.cname
|
||||
+ " ticket for " + asRep.ticket.sname);
|
||||
+ " ticket for " + asRep.ticket.sname + ", flags "
|
||||
+ tFlags);
|
||||
|
||||
DerOutputStream out = new DerOutputStream();
|
||||
out.write(DerValue.createTag(DerValue.TAG_APPLICATION,
|
||||
|
||||
@ -22,7 +22,7 @@
|
||||
*/
|
||||
/*
|
||||
* @test
|
||||
* @bug 6319046
|
||||
* @bug 6319046 8055045
|
||||
* @compile -XDignore.symbol.file ParseConfig.java
|
||||
* @run main/othervm ParseConfig
|
||||
* @summary Problem with parsing krb5.conf
|
||||
@ -32,7 +32,8 @@ import sun.security.krb5.Config;
|
||||
|
||||
public class ParseConfig {
|
||||
public static void main(String[] args) throws Exception {
|
||||
System.setProperty("java.security.krb5.conf", System.getProperty("test.src", ".") +"/krb5.conf");
|
||||
System.setProperty("java.security.krb5.conf",
|
||||
System.getProperty("test.src", ".") + "/krb5.conf");
|
||||
Config config = Config.getInstance();
|
||||
config.listTable();
|
||||
|
||||
@ -44,5 +45,11 @@ public class ParseConfig {
|
||||
expected + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
// JDK-8055045: IOOBE when reading an empty value
|
||||
config.get("empty1", "NOVAL.COM");
|
||||
config.get("empty2", "NOVAL.COM");
|
||||
config.get("quote1", "NOVAL.COM");
|
||||
config.get("quote2", "NOVAL.COM");
|
||||
}
|
||||
}
|
||||
|
||||
@ -27,3 +27,9 @@
|
||||
}
|
||||
}
|
||||
|
||||
NOVAL.COM = {
|
||||
empty1 =
|
||||
empty2 =.
|
||||
quote1 = "
|
||||
quote2 = '
|
||||
}
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2003, 2015, 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
|
||||
@ -58,7 +58,12 @@ public class TimestampCheck {
|
||||
|
||||
static final String defaultPolicyId = "2.3.4.5";
|
||||
|
||||
static class Handler implements HttpHandler {
|
||||
static class Handler implements HttpHandler, AutoCloseable {
|
||||
|
||||
private final HttpServer httpServer;
|
||||
private final String keystore;
|
||||
|
||||
@Override
|
||||
public void handle(HttpExchange t) throws IOException {
|
||||
int len = 0;
|
||||
for (String h: t.getRequestHeaders().keySet()) {
|
||||
@ -136,7 +141,9 @@ public class TimestampCheck {
|
||||
// Write TSResponse
|
||||
System.err.println("\nResponse\n===================");
|
||||
KeyStore ks = KeyStore.getInstance("JKS");
|
||||
ks.load(new FileInputStream(TSKS), "changeit".toCharArray());
|
||||
try (FileInputStream fis = new FileInputStream(keystore)) {
|
||||
ks.load(fis, "changeit".toCharArray());
|
||||
}
|
||||
|
||||
String alias = "ts";
|
||||
if (path == 6) alias = "tsbad1";
|
||||
@ -240,33 +247,74 @@ public class TimestampCheck {
|
||||
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
private Handler(HttpServer httpServer, String keystore) {
|
||||
this.httpServer = httpServer;
|
||||
this.keystore = keystore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize TSA instance.
|
||||
*
|
||||
* Extended Key Info extension of certificate that is used for
|
||||
* signing TSA responses should contain timeStamping value.
|
||||
*/
|
||||
static Handler init(int port, String keystore) throws IOException {
|
||||
HttpServer httpServer = HttpServer.create(
|
||||
new InetSocketAddress(port), 0);
|
||||
Handler tsa = new Handler(httpServer, keystore);
|
||||
httpServer.createContext("/", tsa);
|
||||
return tsa;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start TSA service.
|
||||
*/
|
||||
void start() {
|
||||
httpServer.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop TSA service.
|
||||
*/
|
||||
void stop() {
|
||||
httpServer.stop(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return server port number.
|
||||
*/
|
||||
int getPort() {
|
||||
return httpServer.getAddress().getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws Exception {
|
||||
stop();
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
try (Handler tsa = Handler.init(0, TSKS);) {
|
||||
tsa.start();
|
||||
int port = tsa.getPort();
|
||||
|
||||
Handler h = new Handler();
|
||||
HttpServer server = HttpServer.create(new InetSocketAddress(0), 0);
|
||||
int port = server.getAddress().getPort();
|
||||
HttpContext ctx = server.createContext("/", h);
|
||||
server.start();
|
||||
String cmd;
|
||||
// Use -J-Djava.security.egd=file:/dev/./urandom to speed up
|
||||
// nonce generation in timestamping request. Not avaibale on
|
||||
// Windows and defaults to thread seed generator, not too bad.
|
||||
if (System.getProperty("java.home").endsWith("jre")) {
|
||||
cmd = System.getProperty("java.home") + "/../bin/jarsigner";
|
||||
} else {
|
||||
cmd = System.getProperty("java.home") + "/bin/jarsigner";
|
||||
}
|
||||
|
||||
String cmd = null;
|
||||
// Use -J-Djava.security.egd=file:/dev/./urandom to speed up
|
||||
// nonce generation in timestamping request. Not avaibale on
|
||||
// Windows and defaults to thread seed generator, not too bad.
|
||||
if (System.getProperty("java.home").endsWith("jre")) {
|
||||
cmd = System.getProperty("java.home") + "/../bin/jarsigner";
|
||||
} else {
|
||||
cmd = System.getProperty("java.home") + "/bin/jarsigner";
|
||||
}
|
||||
cmd += " " + System.getProperty("test.tool.vm.opts")
|
||||
+ " -J-Djava.security.egd=file:/dev/./urandom"
|
||||
+ " -debug -keystore " + TSKS + " -storepass changeit"
|
||||
+ " -tsa http://localhost:" + port + "/%d"
|
||||
+ " -signedjar new_%d.jar " + JAR + " old";
|
||||
|
||||
cmd += " " + System.getProperty("test.tool.vm.opts") +
|
||||
" -J-Djava.security.egd=file:/dev/./urandom" +
|
||||
" -debug -keystore " + TSKS + " -storepass changeit" +
|
||||
" -tsa http://localhost:" + port + "/%d" +
|
||||
" -signedjar new_%d.jar " + JAR + " old";
|
||||
|
||||
try {
|
||||
if (args.length == 0) { // Run this test
|
||||
jarsigner(cmd, 0, true); // Success, normal call
|
||||
jarsigner(cmd, 1, false); // These 4 should fail
|
||||
@ -287,8 +335,6 @@ public class TimestampCheck {
|
||||
System.err.println("Press Enter to quit server");
|
||||
System.in.read();
|
||||
}
|
||||
} finally {
|
||||
server.stop(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
147
jdk/test/sun/security/tools/jarsigner/TsacertOptionTest.java
Normal file
147
jdk/test/sun/security/tools/jarsigner/TsacertOptionTest.java
Normal file
@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary The test signs and verifies a jar file with -tsacert option
|
||||
* @library /lib/testlibrary
|
||||
* @run main TsacertOptionTest
|
||||
*/
|
||||
public class TsacertOptionTest {
|
||||
|
||||
private static final String FS = System.getProperty("file.separator");
|
||||
private static final String JAVA_HOME = System.getProperty("java.home");
|
||||
private static final String KEYTOOL = JAVA_HOME + FS + "bin" + FS
|
||||
+ "keytool";
|
||||
private static final String JARSIGNER = JAVA_HOME + FS + "bin" + FS
|
||||
+ "jarsigner";
|
||||
private static final String UNSIGNED_JARFILE = "unsigned.jar";
|
||||
private static final String SIGNED_JARFILE = "signed.jar";
|
||||
private static final String FILENAME = TsacertOptionTest.class.getName()
|
||||
+ ".txt";
|
||||
private static final String PASSWORD = "changeit";
|
||||
private static final String KEYSTORE = "ks.jks";
|
||||
private static final String SIGNING_KEY_ALIAS = "sign_alias";
|
||||
private static final String TSA_KEY_ALIAS = "ts";
|
||||
private static final String KEY_ALG = "RSA";
|
||||
private static final int KEY_SIZE = 2048;
|
||||
private static final int VALIDITY = 365;
|
||||
private static final String WARNING = "Warning:";
|
||||
private static final String JAR_SIGNED = "jar signed.";
|
||||
private static final String JAR_VERIFIED = "jar verified.";
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar file with -tsacert option,
|
||||
* and checks that no warning was shown.
|
||||
* A certificate that is addressed in -tsacert option contains URL to TSA
|
||||
* in Subject Information Access extension.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
TsacertOptionTest test = new TsacertOptionTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
void start() throws Throwable {
|
||||
// create a jar file that contains one file
|
||||
Utils.createFiles(FILENAME);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FILENAME);
|
||||
|
||||
// look for free network port for TSA service
|
||||
int port = jdk.testlibrary.Utils.getFreePort();
|
||||
String host = jdk.testlibrary.Utils.getHostname();
|
||||
String tsaUrl = "http://" + host + ":" + port;
|
||||
|
||||
// create key pair for jar signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", SIGNING_KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Test",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// create key pair for TSA service
|
||||
// SubjectInfoAccess extension contains URL to TSA service
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-v",
|
||||
"-alias", TSA_KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=TSA",
|
||||
"-ext", "ExtendedkeyUsage:critical=timeStamping",
|
||||
"-ext", "SubjectInfoAccess=timeStamping:URI:" + tsaUrl,
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
try (TimestampCheck.Handler tsa = TimestampCheck.Handler.init(port,
|
||||
KEYSTORE);) {
|
||||
|
||||
// start TSA
|
||||
tsa.start();
|
||||
|
||||
// sign jar file
|
||||
// specify -tsadigestalg option because
|
||||
// TSA server uses SHA-1 digest algorithm
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
"-tsacert", TSA_KEY_ALIAS,
|
||||
"-tsadigestalg", "SHA-1",
|
||||
UNSIGNED_JARFILE,
|
||||
SIGNING_KEY_ALIAS);
|
||||
|
||||
analyzer.shouldHaveExitValue(0);
|
||||
analyzer.stdoutShouldNotContain(WARNING);
|
||||
analyzer.shouldContain(JAR_SIGNED);
|
||||
|
||||
// verify signed jar
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verbose",
|
||||
"-verify",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
analyzer.shouldHaveExitValue(0);
|
||||
analyzer.stdoutShouldNotContain(WARNING);
|
||||
analyzer.shouldContain(JAR_VERIFIED);
|
||||
}
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
39
jdk/test/sun/security/tools/jarsigner/Utils.java
Normal file
39
jdk/test/sun/security/tools/jarsigner/Utils.java
Normal file
@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Helper class.
|
||||
*/
|
||||
public class Utils {
|
||||
|
||||
static void createFiles(String... filenames) throws IOException {
|
||||
for (String filename : filenames) {
|
||||
new File(filename).createNewFile();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Test for aliasNotInStore warning
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main AliasNotInStoreTest
|
||||
*/
|
||||
public class AliasNotInStoreTest extends Test {
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that contains signed entries
|
||||
* that are not signed by any alias in keystore (aliasNotInStore).
|
||||
* Warning message is expected.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
AliasNotInStoreTest test = new AliasNotInStoreTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
private void start() throws Throwable {
|
||||
Utils.createFiles(FIRST_FILE, SECOND_FILE);
|
||||
System.out.println(String.format("Create a %s that contains %s",
|
||||
new Object[]{UNSIGNED_JARFILE, FIRST_FILE}));
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create first key pair for signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", FIRST_KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", BOTH_KEYS_KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=First",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// create second key pair for signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", SECOND_KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", BOTH_KEYS_KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Second",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// sign jar with first key
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-keystore", BOTH_KEYS_KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
FIRST_KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer);
|
||||
|
||||
System.out.println(String.format("Copy %s to %s, and add %s",
|
||||
new Object[] {SIGNED_JARFILE, UPDATED_SIGNED_JARFILE,
|
||||
SECOND_FILE}));
|
||||
|
||||
JarUtils.updateJar(SIGNED_JARFILE, UPDATED_SIGNED_JARFILE, SECOND_FILE);
|
||||
|
||||
// sign jar with second key
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-keystore", BOTH_KEYS_KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
UPDATED_SIGNED_JARFILE,
|
||||
SECOND_KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer);
|
||||
|
||||
// create keystore that contains only first key
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-importkeystore",
|
||||
"-srckeystore", BOTH_KEYS_KEYSTORE,
|
||||
"-srcalias", FIRST_KEY_ALIAS,
|
||||
"-srcstorepass", PASSWORD,
|
||||
"-srckeypass", PASSWORD,
|
||||
"-destkeystore", FIRST_KEY_KEYSTORE,
|
||||
"-destalias", FIRST_KEY_ALIAS,
|
||||
"-deststorepass", PASSWORD,
|
||||
"-destkeypass", PASSWORD).shouldHaveExitValue(0);
|
||||
|
||||
// verify jar with keystore that contains only first key in strict mode,
|
||||
// so there is signed entry (FirstClass.class) that is not signed
|
||||
// by any alias in the keystore
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-keystore", FIRST_KEY_KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
UPDATED_SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, 0, CHAIN_NOT_VALIDATED_VERIFYING_WARNING,
|
||||
ALIAS_NOT_IN_STORE_VERIFYING_WARNING);
|
||||
|
||||
// verify jar with keystore that contains only first key in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-strict",
|
||||
"-keystore", FIRST_KEY_KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
UPDATED_SIGNED_JARFILE);
|
||||
|
||||
int expectedExitCode = ALIAS_NOT_IN_STORE_EXIT_CODE
|
||||
+ CHAIN_NOT_VALIDATED_EXIT_CODE;
|
||||
checkVerifying(analyzer, expectedExitCode,
|
||||
CHAIN_NOT_VALIDATED_VERIFYING_WARNING,
|
||||
ALIAS_NOT_IN_STORE_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,106 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Test for badExtendedKeyUsage warning
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main BadExtendedKeyUsageTest
|
||||
*/
|
||||
public class BadExtendedKeyUsageTest extends Test {
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that contains entries
|
||||
* whose signer certificate's ExtendedKeyUsage extension
|
||||
* doesn't allow code signing (badExtendedKeyUsage).
|
||||
* Warning message is expected.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
BadExtendedKeyUsageTest test = new BadExtendedKeyUsageTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
private void start() throws Throwable {
|
||||
// create a jar file that contains one class file
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create a certificate whose signer certificate's
|
||||
// ExtendedKeyUsage extension doesn't allow code signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Test",
|
||||
"-ext", "ExtendedkeyUsage=serverAuth",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// sign jar
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer, BAD_EXTENDED_KEY_USAGE_SIGNING_WARNING);
|
||||
|
||||
// verify signed jar
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, 0, BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING);
|
||||
|
||||
// verity signed jar in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, BAD_EXTENDED_KEY_USAGE_EXIT_CODE,
|
||||
BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Test for badKeyUsage warning
|
||||
* @library /lib/testlibrary ../
|
||||
* @ignore until 8026393 is fixed
|
||||
* @run main BadKeyUsageTest
|
||||
*/
|
||||
public class BadKeyUsageTest extends Test {
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that contains entries
|
||||
* whose signer certificate's KeyUsage extension
|
||||
* doesn't allow code signing (badKeyUsage).
|
||||
* Warning message is expected.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
BadKeyUsageTest test = new BadKeyUsageTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
private void start() throws Throwable {
|
||||
// create a jar file that contains one class file
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create a certificate whose signer certificate's KeyUsage extension
|
||||
// doesn't allow code signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Test",
|
||||
"-ext", "KeyUsage=keyAgreement",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// sign jar
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer, BAD_KEY_USAGE_SIGNING_WARNING);
|
||||
|
||||
// verify signed jar
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, 0, BAD_KEY_USAGE_VERIFYING_WARNING);
|
||||
|
||||
// verify signed jar in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, BAD_KEY_USAGE_EXIT_CODE,
|
||||
BAD_KEY_USAGE_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Base64;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Test for badNetscapeCertType warning
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main BadNetscapeCertTypeTest
|
||||
*/
|
||||
public class BadNetscapeCertTypeTest extends Test {
|
||||
|
||||
private static final String NETSCAPE_KEYSTORE_BASE64 = TEST_SOURCES + FS
|
||||
+ "bad_netscape_cert_type.jks.base64";
|
||||
|
||||
private static final String NETSCAPE_KEYSTORE
|
||||
= "bad_netscape_cert_type.jks";
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that contains entries
|
||||
* whose signer certificate's NetscapeCertType extension
|
||||
* doesn't allow code signing (badNetscapeCertType).
|
||||
* Warning message is expected.
|
||||
* Run bad_netscape_cert_type.sh script to create bad_netscape_cert_type.jks
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
|
||||
Files.write(Paths.get(NETSCAPE_KEYSTORE),
|
||||
Base64.getMimeDecoder().decode(
|
||||
Files.readAllBytes(Paths.get(NETSCAPE_KEYSTORE_BASE64))));
|
||||
|
||||
BadNetscapeCertTypeTest test = new BadNetscapeCertTypeTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
private void start() throws Throwable {
|
||||
// create a jar file that contains one class file
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// sign jar
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verbose",
|
||||
"-keystore", NETSCAPE_KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer, BAD_NETSCAPE_CERT_TYPE_SIGNING_WARNING);
|
||||
|
||||
// verify signed jar
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-keystore", NETSCAPE_KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, 0, BAD_NETSCAPE_CERT_TYPE_VERIFYING_WARNING);
|
||||
|
||||
// verify signed jar in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-strict",
|
||||
"-keystore", NETSCAPE_KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, BAD_NETSCAPE_CERT_TYPE_EXIT_CODE,
|
||||
BAD_NETSCAPE_CERT_TYPE_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Test for chainNotValidated warning
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main ChainNotValidatedTest
|
||||
*/
|
||||
public class ChainNotValidatedTest extends Test {
|
||||
|
||||
private static final String CHAIN = "chain";
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that contains entries
|
||||
* whose cert chain can't be correctly validated (chainNotValidated).
|
||||
* Warning message is expected.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
ChainNotValidatedTest test = new ChainNotValidatedTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
private void start() throws Throwable {
|
||||
// create a jar file that contains one class file
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create self-signed certificate whose BasicConstraints extension
|
||||
// is set to false, so the certificate may not be used
|
||||
// as a parent certificate (certpath validation should fail)
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkeypair",
|
||||
"-alias", CA_KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=CA",
|
||||
"-ext", "BasicConstraints:critical=ca:false",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// create a certificate that is signed by self-signed certificate
|
||||
// despite of it may not be used as a parent certificate
|
||||
// (certpath validation should fail)
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkeypair",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Test",
|
||||
"-ext", "BasicConstraints:critical=ca:false",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-certreq",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-file", CERT_REQUEST_FILENAME).shouldHaveExitValue(0);
|
||||
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-gencert",
|
||||
"-alias", CA_KEY_ALIAS,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-infile", CERT_REQUEST_FILENAME,
|
||||
"-validity", Integer.toString(VALIDITY),
|
||||
"-outfile", CERT_FILENAME).shouldHaveExitValue(0);
|
||||
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-importcert",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-file", CERT_FILENAME).shouldHaveExitValue(0);
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(KEYTOOL,
|
||||
"-export",
|
||||
"-rfc",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD);
|
||||
pb.redirectOutput(ProcessBuilder.Redirect.appendTo(new File(CHAIN)));
|
||||
ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
|
||||
|
||||
pb = new ProcessBuilder(KEYTOOL,
|
||||
"-export",
|
||||
"-rfc",
|
||||
"-alias", CA_KEY_ALIAS,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD);
|
||||
pb.redirectOutput(ProcessBuilder.Redirect.appendTo(new File(CHAIN)));
|
||||
ProcessTools.executeCommand(pb).shouldHaveExitValue(0);
|
||||
|
||||
// remove CA certificate
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-delete",
|
||||
"-alias", CA_KEY_ALIAS,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD).shouldHaveExitValue(0);
|
||||
|
||||
// sign jar
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-certchain", CHAIN,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer, CHAIN_NOT_VALIDATED_SIGNING_WARNING);
|
||||
|
||||
// verify signed jar
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-certchain", CHAIN,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, 0, CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
|
||||
|
||||
// verify signed jar in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-certchain", CHAIN,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, CHAIN_NOT_VALIDATED_EXIT_CODE,
|
||||
CHAIN_NOT_VALIDATED_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Test for hasExpiredCert warning
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main HasExpiredCertTest
|
||||
*/
|
||||
public class HasExpiredCertTest extends Test {
|
||||
|
||||
static final int SHORT_VALIDITY = 365;
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that contains entries
|
||||
* whose signer certificate has expired (hasExpiredCert).
|
||||
* Warning message is expected.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
HasExpiredCertTest test = new HasExpiredCertTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
private void start() throws Throwable {
|
||||
// create a jar file that contains one class file
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create key pair for jar signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Test",
|
||||
"-startdate", "-" + SHORT_VALIDITY * 2 + "d",
|
||||
"-validity", Integer.toString(SHORT_VALIDITY))
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// sign jar
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer, HAS_EXPIRED_CERT_SIGNING_WARNING);
|
||||
|
||||
// verify signed jar
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, 0, HAS_EXPIRED_CERT_VERIFYING_WARNING);
|
||||
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, HAS_EXPIRED_CERT_EXIT_CODE,
|
||||
HAS_EXPIRED_CERT_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Test for hasExpiringCert warning
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main HasExpiringCertTest
|
||||
*/
|
||||
public class HasExpiringCertTest extends Test {
|
||||
|
||||
static final int SHORT_VALIDITY = 90; // less than 6 month
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that contains entries
|
||||
* whose signer certificate will expire within six months (hasExpiringCert).
|
||||
* Warning message is expected.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
HasExpiringCertTest test = new HasExpiringCertTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
private void start() throws Throwable {
|
||||
// create a jar file that contains one class file
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create key pair for jar signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Test",
|
||||
"-validity", Integer.toString(SHORT_VALIDITY))
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// sign jar
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-keystore", KEYSTORE,
|
||||
"-verbose",
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer, HAS_EXPIRING_CERT_SIGNING_WARNING);
|
||||
|
||||
// verify signed jar
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkVerifying(analyzer, 0, HAS_EXPIRING_CERT_VERIFYING_WARNING);
|
||||
|
||||
// verify signed jar in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkVerifying(analyzer, 0, HAS_EXPIRING_CERT_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Test for hasUnsignedEntry warning
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main HasUnsignedEntryTest
|
||||
*/
|
||||
public class HasUnsignedEntryTest extends Test {
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that contains unsigned entries
|
||||
* which have not been integrity-checked (hasUnsignedEntry).
|
||||
* Warning message is expected.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
HasUnsignedEntryTest test = new HasUnsignedEntryTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
private void start() throws Throwable {
|
||||
System.out.println(String.format("Create a %s that contains %s",
|
||||
UNSIGNED_JARFILE, FIRST_FILE));
|
||||
Utils.createFiles(FIRST_FILE, SECOND_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create key pair for signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Test",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// sign jar
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer);
|
||||
|
||||
System.out.println(String.format("Copy %s to %s, and add %s.class, "
|
||||
+ "so it contains unsigned entry",
|
||||
new Object[]{SIGNED_JARFILE, UPDATED_SIGNED_JARFILE,
|
||||
SECOND_FILE}));
|
||||
|
||||
JarUtils.updateJar(SIGNED_JARFILE, UPDATED_SIGNED_JARFILE, SECOND_FILE);
|
||||
|
||||
// verify jar
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
UPDATED_SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, 0, HAS_UNSIGNED_ENTRY_VERIFYING_WARNING);
|
||||
|
||||
// verify jar in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
UPDATED_SIGNED_JARFILE);
|
||||
|
||||
checkVerifying(analyzer, HAS_UNSIGNED_ENTRY_EXIT_CODE,
|
||||
HAS_UNSIGNED_ENTRY_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,169 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Checks if jarsigner prints appropriate warnings
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main MultipleWarningsTest
|
||||
*/
|
||||
public class MultipleWarningsTest extends Test {
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that:
|
||||
* - contains entries whose signer certificate has expired
|
||||
* - contains entries whose signer certificate's ExtendedKeyUsage
|
||||
* extension doesn't allow code signing
|
||||
* - contains unsigned entries which have not been integrity-checked
|
||||
* - contains signed entries which are not signed by the specified alias
|
||||
* Warning messages are expected.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
MultipleWarningsTest test = new MultipleWarningsTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
private void start() throws Throwable {
|
||||
Utils.createFiles(FIRST_FILE, SECOND_FILE);
|
||||
|
||||
// create a jar file that contains one class file
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create first expired certificate
|
||||
// whose ExtendedKeyUsage extension does not allow code signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", FIRST_KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=First",
|
||||
"-ext", "ExtendedkeyUsage=serverAuth",
|
||||
"-startdate", "-" + VALIDITY * 2 + "d",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// create second expired certificate
|
||||
// whose KeyUsage extension does not allow code signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", SECOND_KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Second",
|
||||
"-ext", "ExtendedkeyUsage=serverAuth",
|
||||
"-startdate", "-" + VALIDITY * 2 + "d",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// sign jar with first key
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
FIRST_KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer, HAS_EXPIRED_CERT_SIGNING_WARNING,
|
||||
BAD_EXTENDED_KEY_USAGE_SIGNING_WARNING);
|
||||
|
||||
// add a second class to created jar, so it contains unsigned entry
|
||||
JarUtils.updateJar(SIGNED_JARFILE, UPDATED_SIGNED_JARFILE, SECOND_FILE);
|
||||
|
||||
// verify jar with second key
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
UPDATED_SIGNED_JARFILE,
|
||||
SECOND_KEY_ALIAS);
|
||||
|
||||
checkVerifying(analyzer, 0, BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
|
||||
HAS_EXPIRED_CERT_VERIFYING_WARNING,
|
||||
HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
|
||||
NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
|
||||
|
||||
// verify jar with second key in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
UPDATED_SIGNED_JARFILE,
|
||||
SECOND_KEY_ALIAS);
|
||||
|
||||
int expectedExitCode = HAS_EXPIRED_CERT_EXIT_CODE
|
||||
+ BAD_EXTENDED_KEY_USAGE_EXIT_CODE
|
||||
+ HAS_UNSIGNED_ENTRY_EXIT_CODE
|
||||
+ NOT_SIGNED_BY_ALIAS_EXIT_CODE;
|
||||
checkVerifying(analyzer, expectedExitCode,
|
||||
BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
|
||||
HAS_EXPIRED_CERT_VERIFYING_WARNING,
|
||||
HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
|
||||
NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
|
||||
|
||||
// verify jar with non-exisiting alias
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
UPDATED_SIGNED_JARFILE,
|
||||
"bogus");
|
||||
|
||||
checkVerifying(analyzer, 0, BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
|
||||
HAS_EXPIRED_CERT_VERIFYING_WARNING,
|
||||
HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
|
||||
NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
|
||||
|
||||
// verify jar with non-exisiting alias in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
UPDATED_SIGNED_JARFILE,
|
||||
"bogus");
|
||||
|
||||
checkVerifying(analyzer, expectedExitCode,
|
||||
BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING,
|
||||
HAS_EXPIRED_CERT_VERIFYING_WARNING,
|
||||
HAS_UNSIGNED_ENTRY_VERIFYING_WARNING,
|
||||
NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import java.util.Date;
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Checks warnings if -tsa and -tsacert options are not specified
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main NoTimestampTest
|
||||
*/
|
||||
public class NoTimestampTest extends Test {
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar file without -tsa and -tsacert options,
|
||||
* and checks that proper warnings are shown.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
NoTimestampTest test = new NoTimestampTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
private void start() throws Throwable {
|
||||
String timezone = System.getProperty("user.timezone");
|
||||
System.out.println(String.format("Timezone = %s", timezone));
|
||||
|
||||
// create a jar file that contains one class file
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// calculate certificate expiration date
|
||||
Date expirationDate = new Date(System.currentTimeMillis() + VALIDITY
|
||||
* 24 * 60 * 60 * 1000L);
|
||||
|
||||
// create key pair
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Test",
|
||||
"-validity", Integer.toString(VALIDITY));
|
||||
|
||||
// sign jar file
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-J-Duser.timezone=" + timezone,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
String warning = String.format(NO_TIMESTAMP_SIGNING_WARN_TEMPLATE,
|
||||
expirationDate);
|
||||
checkSigning(analyzer, warning);
|
||||
|
||||
// verify signed jar
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-J-Duser.timezone=" + timezone,
|
||||
"-verify",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
warning = String.format(NO_TIMESTAMP_VERIFYING_WARN_TEMPLATE, expirationDate);
|
||||
checkVerifying(analyzer, 0, warning);
|
||||
|
||||
// verify signed jar in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-J-Duser.timezone=" + timezone,
|
||||
"-verify",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkVerifying(analyzer, 0, warning);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Test for notSignedByAlias warning
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main NotSignedByAliasTest
|
||||
*/
|
||||
public class NotSignedByAliasTest extends Test {
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that contains signed entries
|
||||
* which are not signed by the specified alias(es) (notSignedByAlias).
|
||||
* Warning message is expected.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
NotSignedByAliasTest test = new NotSignedByAliasTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
protected void start() throws Throwable {
|
||||
// create a jar file that contains one class file
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create first key pair for signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", FIRST_KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=First",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// create first key pair for signing
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", SECOND_KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Second",
|
||||
"-validity", Integer.toString(VALIDITY)).shouldHaveExitValue(0);
|
||||
|
||||
// sign jar with first key
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
FIRST_KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer);
|
||||
|
||||
// verify jar with second key
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE,
|
||||
SECOND_KEY_ALIAS);
|
||||
|
||||
checkVerifying(analyzer, 0, NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
|
||||
|
||||
// verify jar with second key in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE,
|
||||
SECOND_KEY_ALIAS);
|
||||
|
||||
checkVerifying(analyzer, NOT_SIGNED_BY_ALIAS_EXIT_CODE,
|
||||
NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
|
||||
|
||||
// verify jar with non-existing alias
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE,
|
||||
"bogus");
|
||||
|
||||
checkVerifying(analyzer, 0, NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
|
||||
|
||||
// verify jar with non-existing alias in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE,
|
||||
"bogus");
|
||||
|
||||
checkVerifying(analyzer, NOT_SIGNED_BY_ALIAS_EXIT_CODE,
|
||||
NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
import jdk.testlibrary.ProcessTools;
|
||||
import jdk.testlibrary.JarUtils;
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8024302 8026037
|
||||
* @summary Test for notYetValidCert warning
|
||||
* @library /lib/testlibrary ../
|
||||
* @run main NotYetValidCertTest
|
||||
*/
|
||||
public class NotYetValidCertTest extends Test {
|
||||
|
||||
/**
|
||||
* The test signs and verifies a jar that contains entries
|
||||
* whose signer certificate is not yet valid (notYetValidCert).
|
||||
* Warning message is expected.
|
||||
*/
|
||||
public static void main(String[] args) throws Throwable {
|
||||
NotYetValidCertTest test = new NotYetValidCertTest();
|
||||
test.start();
|
||||
}
|
||||
|
||||
protected void start() throws Throwable {
|
||||
// create a jar file that contains one class file
|
||||
Utils.createFiles(FIRST_FILE);
|
||||
JarUtils.createJar(UNSIGNED_JARFILE, FIRST_FILE);
|
||||
|
||||
// create certificate that will be valid only tomorrow
|
||||
ProcessTools.executeCommand(KEYTOOL,
|
||||
"-genkey",
|
||||
"-alias", KEY_ALIAS,
|
||||
"-keyalg", KEY_ALG,
|
||||
"-keysize", Integer.toString(KEY_SIZE),
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-dname", "CN=Test",
|
||||
"-startdate", "+1d",
|
||||
"-validity", Integer.toString(VALIDITY));
|
||||
|
||||
// sign jar
|
||||
OutputAnalyzer analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
"-signedjar", SIGNED_JARFILE,
|
||||
UNSIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkSigning(analyzer, NOT_YET_VALID_CERT_SIGNING_WARNING);
|
||||
|
||||
// verify signed jar
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkVerifying(analyzer, 0, NOT_YET_VALID_CERT_VERIFYING_WARNING);
|
||||
|
||||
// verify jar in strict mode
|
||||
analyzer = ProcessTools.executeCommand(JARSIGNER,
|
||||
"-verify",
|
||||
"-verbose",
|
||||
"-strict",
|
||||
"-keystore", KEYSTORE,
|
||||
"-storepass", PASSWORD,
|
||||
"-keypass", PASSWORD,
|
||||
SIGNED_JARFILE,
|
||||
KEY_ALIAS);
|
||||
|
||||
checkVerifying(analyzer, HAS_EXPIRED_CERT_EXIT_CODE,
|
||||
NOT_YET_VALID_CERT_VERIFYING_WARNING);
|
||||
|
||||
System.out.println("Test passed");
|
||||
}
|
||||
|
||||
}
|
||||
178
jdk/test/sun/security/tools/jarsigner/warnings/Test.java
Normal file
178
jdk/test/sun/security/tools/jarsigner/warnings/Test.java
Normal file
@ -0,0 +1,178 @@
|
||||
/*
|
||||
* Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import jdk.testlibrary.OutputAnalyzer;
|
||||
|
||||
/**
|
||||
* Base class.
|
||||
*/
|
||||
public abstract class Test {
|
||||
|
||||
static final String TEST_SOURCES = System.getProperty("test.src", ".");
|
||||
static final String TEST_CLASSES = System.getProperty("test.classes");
|
||||
static final String FS = System.getProperty("file.separator");
|
||||
static final String JAVA_HOME = System.getProperty("java.home");
|
||||
static final String KEYTOOL = JAVA_HOME + FS + "bin" + FS + "keytool";
|
||||
static final String JARSIGNER = JAVA_HOME + FS + "bin" + FS + "jarsigner";
|
||||
static final String UNSIGNED_JARFILE = "unsigned.jar";
|
||||
static final String SIGNED_JARFILE = "signed.jar";
|
||||
static final String UPDATED_SIGNED_JARFILE = "updated_signed.jar";
|
||||
static final String FIRST_FILE = "first.txt";
|
||||
static final String SECOND_FILE = "second.txt";
|
||||
static final String PASSWORD = "password";
|
||||
static final String BOTH_KEYS_KEYSTORE = "both_keys.jks";
|
||||
static final String FIRST_KEY_KEYSTORE = "first_key.jks";
|
||||
static final String KEYSTORE = "keystore.jks";
|
||||
static final String FIRST_KEY_ALIAS = "first";
|
||||
static final String SECOND_KEY_ALIAS = "second";
|
||||
static final String KEY_ALG = "RSA";
|
||||
static final String KEY_ALIAS = "alias";
|
||||
static final String CERT_REQUEST_FILENAME = "test.req";
|
||||
static final String CERT_FILENAME = "test.crt";
|
||||
static final String CA_KEY_ALIAS = "ca";
|
||||
static final int KEY_SIZE = 2048;
|
||||
static final int TIMEOUT = 6 * 60 * 1000; // in millis
|
||||
static final int VALIDITY = 365;
|
||||
|
||||
static final String WARNING = "Warning:";
|
||||
|
||||
static final String CHAIN_NOT_VALIDATED_VERIFYING_WARNING
|
||||
= "This jar contains entries "
|
||||
+ "whose certificate chain is not validated.";
|
||||
|
||||
static final String ALIAS_NOT_IN_STORE_VERIFYING_WARNING
|
||||
= "This jar contains signed entries "
|
||||
+ "that are not signed by alias in this keystore.";
|
||||
|
||||
static final String BAD_EXTENDED_KEY_USAGE_SIGNING_WARNING
|
||||
= "The signer certificate's ExtendedKeyUsage extension "
|
||||
+ "doesn't allow code signing.";
|
||||
|
||||
static final String BAD_EXTENDED_KEY_USAGE_VERIFYING_WARNING
|
||||
= "This jar contains entries whose signer certificate's "
|
||||
+ "ExtendedKeyUsage extension doesn't allow code signing.";
|
||||
|
||||
static final String BAD_KEY_USAGE_SIGNING_WARNING
|
||||
= "The signer certificate's KeyUsage extension "
|
||||
+ "doesn't allow code signing.";
|
||||
|
||||
static final String BAD_KEY_USAGE_VERIFYING_WARNING
|
||||
= "This jar contains entries whose signer certificate's KeyUsage "
|
||||
+ "extension doesn't allow code signing.";
|
||||
|
||||
static final String BAD_NETSCAPE_CERT_TYPE_SIGNING_WARNING
|
||||
= "The signer certificate's NetscapeCertType extension "
|
||||
+ "doesn't allow code signing.";
|
||||
|
||||
static final String BAD_NETSCAPE_CERT_TYPE_VERIFYING_WARNING
|
||||
= "This jar contains entries "
|
||||
+ "whose signer certificate's NetscapeCertType extension "
|
||||
+ "doesn't allow code signing.";
|
||||
|
||||
static final String CHAIN_NOT_VALIDATED_SIGNING_WARNING
|
||||
= "The signer's certificate chain is not validated.";
|
||||
|
||||
static final String HAS_EXPIRING_CERT_SIGNING_WARNING
|
||||
= "The signer certificate will expire within six months.";
|
||||
|
||||
static final String HAS_EXPIRING_CERT_VERIFYING_WARNING
|
||||
= "This jar contains entries "
|
||||
+ "whose signer certificate will expire within six months.";
|
||||
|
||||
static final String HAS_EXPIRED_CERT_SIGNING_WARNING
|
||||
= "The signer certificate has expired.";
|
||||
|
||||
static final String HAS_EXPIRED_CERT_VERIFYING_WARNING
|
||||
= "This jar contains entries whose signer certificate has expired.";
|
||||
|
||||
static final String HAS_UNSIGNED_ENTRY_VERIFYING_WARNING
|
||||
= "This jar contains unsigned entries "
|
||||
+ "which have not been integrity-checked.";
|
||||
|
||||
static final String NOT_SIGNED_BY_ALIAS_VERIFYING_WARNING
|
||||
= "This jar contains signed entries "
|
||||
+ "which are not signed by the specified alias(es).";
|
||||
|
||||
static final String NO_TIMESTAMP_SIGNING_WARN_TEMPLATE
|
||||
= "No -tsa or -tsacert is provided "
|
||||
+ "and this jar is not timestamped. "
|
||||
+ "Without a timestamp, users may not be able to validate this jar "
|
||||
+ "after the signer certificate's expiration date "
|
||||
+ "(%1$tY-%1$tm-%1$td) or after any future revocation date.";
|
||||
|
||||
static final String NO_TIMESTAMP_VERIFYING_WARN_TEMPLATE
|
||||
= "This jar contains signatures that does not include a timestamp. "
|
||||
+ "Without a timestamp, users may not be able to validate this jar "
|
||||
+ "after the signer certificate's expiration date "
|
||||
+ "(%1$tY-%1$tm-%1$td) or after any future revocation date.";
|
||||
|
||||
static final String NOT_YET_VALID_CERT_SIGNING_WARNING
|
||||
= "The signer certificate is not yet valid.";
|
||||
|
||||
static final String NOT_YET_VALID_CERT_VERIFYING_WARNING
|
||||
= "This jar contains entries "
|
||||
+ "whose signer certificate is not yet valid.";
|
||||
|
||||
static final String JAR_SIGNED = "jar signed.";
|
||||
|
||||
static final String JAR_VERIFIED = "jar verified.";
|
||||
|
||||
static final String JAR_VERIFIED_WITH_SIGNER_ERRORS
|
||||
= "jar verified, with signer errors.";
|
||||
|
||||
static final int CHAIN_NOT_VALIDATED_EXIT_CODE = 4;
|
||||
static final int HAS_EXPIRED_CERT_EXIT_CODE = 4;
|
||||
static final int BAD_KEY_USAGE_EXIT_CODE = 8;
|
||||
static final int BAD_EXTENDED_KEY_USAGE_EXIT_CODE = 8;
|
||||
static final int BAD_NETSCAPE_CERT_TYPE_EXIT_CODE = 8;
|
||||
static final int HAS_UNSIGNED_ENTRY_EXIT_CODE = 16;
|
||||
static final int ALIAS_NOT_IN_STORE_EXIT_CODE = 32;
|
||||
static final int NOT_SIGNED_BY_ALIAS_EXIT_CODE = 32;
|
||||
|
||||
protected void checkVerifying(OutputAnalyzer analyzer, int expectedExitCode,
|
||||
String... warnings) {
|
||||
analyzer.shouldHaveExitValue(expectedExitCode);
|
||||
for (String warning : warnings) {
|
||||
analyzer.shouldContain(warning);
|
||||
}
|
||||
if (warnings.length > 0) {
|
||||
analyzer.shouldContain(WARNING);
|
||||
}
|
||||
if (expectedExitCode == 0) {
|
||||
analyzer.shouldContain(JAR_VERIFIED);
|
||||
} else {
|
||||
analyzer.shouldContain(JAR_VERIFIED_WITH_SIGNER_ERRORS);
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkSigning(OutputAnalyzer analyzer, String... warnings) {
|
||||
analyzer.shouldHaveExitValue(0);
|
||||
for (String warning : warnings) {
|
||||
analyzer.shouldContain(warning);
|
||||
}
|
||||
if (warnings.length > 0) {
|
||||
analyzer.shouldContain(WARNING);
|
||||
}
|
||||
analyzer.shouldContain(JAR_SIGNED);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
/u3+7QAAAAIAAAABAAAAAQAFYWxpYXMAAAFBpkwW0gAAAr0wggK5MA4GCisGAQQB
|
||||
KgIRAQEFAASCAqWkGJ3PPjYmWNKrV23Y1u413RMAkrRZ+1OLWYRcQt4jtxtIyEH5
|
||||
Ho5b9dy9XN9FBKlTOD4c2Pc1T43BLKXeuLu3uLLeIxgXFt0z9CLyGwdYZZ751kXr
|
||||
DQ99qY6aNQUO6SeE4Wdty0KPAqid6ZJ8bF7T6wsTZSvNhaBRzyFydEfG7bbUYjOl
|
||||
mWC44nlsu6VEU3o9RQpcm1gIMwradOaIVT/HoB2bKmAv8gHqI6kreiEZwTdZkSAI
|
||||
IRi2vt1RPllXt5hgjDxUfZe8XOYYweR4Vt2/jVuKLJ80DNTu/9SeUD88zQAz53k4
|
||||
r3nRhv6TRcPm6tV/Fh92XLHiskL+TAzTfm+bUAudPCCVxN+yRtxvAgA+UhdV/SuM
|
||||
Zn5F6nrmP+YJG1hmprgCJIJJaCEXa9RXYC+vIVpO0WVNRuGlGm+/1afnOuQC8Wss
|
||||
ShXwjkaqTwAhqBFq7eYmmP8BK3gflYrt2zDLXvhl4ndVvMhMthFJ3ZvLh2LWpqLI
|
||||
/n8EMCf8US3lIEFk9DTHBZjffiHkqK2e7+FXEpG3xrgE6ZYLMdbd5Pb3YjZfhQx+
|
||||
ZTtiEFzYSaEGhacek/m7dRq1qmwgFsytng2OdWZe2ln8LJY0odr1dGUfJHfgafvi
|
||||
tlfbkg/rgjONtwliChDggbkUwnerrj/D/zrdEufUvfyltSshhHXRNDD3fH6spmEk
|
||||
hHKgxEc4yvxqJxzdMGtuib355aSfNegyl+GsnsKzXQCVEK2h3BLTQObzaD+8NZ12
|
||||
LQHvbrCiaS34vxJ3rEC+a+SW7itZp0aCdXMWdMJNkRKqyLBD3vG3zN05sN3XrhEM
|
||||
8BRT020TWY00tbVFbbBFheYLQRgTjrQtr0Yt6UHWBZc4N20crDLcSH5gqcCOVpla
|
||||
1Y2uqFEn8yqrGRwn/kgfNgAAAAEABVguNTA5AAABtTCCAbEwggEaoAMCAQICCQDH
|
||||
cEuVvzCuqzANBgkqhkiG9w0BAQUFADAPMQ0wCwYDVQQDDARUZXN0MB4XDTEzMTAx
|
||||
MTA2NTUwNloXDTIzMTAwOTA2NTUwNlowDzENMAsGA1UEAwwEVGVzdDCBnzANBgkq
|
||||
hkiG9w0BAQEFAAOBjQAwgYkCgYEA8hOfp2Dcnvt//ZZQAja9TRiwKqXVS+TiYE3S
|
||||
gngCBjIi+YYdo0DsUeO5MBfE6uvCWOr5lwAR/u1iaJOhIoGJDiGoPasZlt+yIgtR
|
||||
LzA7j2q+1q6kcwiVxfikI3aUgHV/QsybTriT4Bf7TQNKtJG23MQa4sD7+PjtCWD7
|
||||
p3cHTfkCAwEAAaMVMBMwEQYJYIZIAYb4QgEBBAQDAgeAMA0GCSqGSIb3DQEBBQUA
|
||||
A4GBAKoDlTJ8wLRA7G8XdGm4gv733n1cSQzlkcsjfOO6/mA5Jvu8tyFNq9HTf9AT
|
||||
VXbrbGcUYJjhzSSY3w5apXK1kXyqTB1LUNEJ45WnmciqSSecVTpJz9TuegyoX0Zf
|
||||
HScSgqfDmjqoiiFiNCgn3ZEJ85ykGvoFYGH+php+BVi3S0bj5E/jRpyV3vNnii/S
|
||||
wJDSAXF6bYU=
|
||||
@ -0,0 +1,48 @@
|
||||
#
|
||||
# Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
#
|
||||
# This code is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License version 2 only, as
|
||||
# published by the Free Software Foundation.
|
||||
#
|
||||
# This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
# version 2 for more details (a copy is included in the LICENSE file that
|
||||
# accompanied this code).
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License version
|
||||
# 2 along with this work; if not, write to the Free Software Foundation,
|
||||
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
#
|
||||
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
# or visit www.oracle.com if you need additional information or have any
|
||||
# questions.
|
||||
#
|
||||
|
||||
#!/bin/sh
|
||||
|
||||
# This script creates JKS keystore with a certificate
|
||||
# that contains Netscape Certificate Type extension
|
||||
# that does not allow code signing
|
||||
# The keystore is used by BadNetscapeCertTypeTest.java test
|
||||
|
||||
rm -rf keystore.jks
|
||||
echo "nsCertType = client" > ext.cfg
|
||||
|
||||
openssl req -new -out cert.req -keyout key.pem -days 3650 \
|
||||
-passin pass:password -passout pass:password -subj "/CN=Test"
|
||||
openssl x509 -in cert.req -out cert.pem -req -signkey key.pem -days 3650 \
|
||||
-passin pass:password -extfile ext.cfg
|
||||
openssl pkcs12 -export -in cert.pem -inkey key.pem -out keystore.p12 \
|
||||
-passin pass:password -passout pass:password -name alias
|
||||
|
||||
${JAVA_HOME}/bin/keytool -importkeystore \
|
||||
-srckeystore keystore.p12 -srcstoretype pkcs12 \
|
||||
-srcstorepass password -alias alias \
|
||||
-destkeystore bad_netscape_cert_type.jks -deststoretype jks \
|
||||
-deststorepass password -destalias alias \
|
||||
|
||||
openssl base64 < bad_netscape_cert_type.jks > bad_netscape_cert_type.jks.base64
|
||||
rm -rf cert.req key.pem cert.pem keystore.p12 ext.cfg bad_netscape_cert_type.jks
|
||||
132
jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java
Normal file
132
jdk/test/sun/tools/jmap/heapconfig/JMapHeapConfigTest.java
Normal file
@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8042397
|
||||
* @summary Unit test for jmap utility test heap configuration reader
|
||||
* @library /lib/testlibrary
|
||||
* @build jdk.testlibrary.*
|
||||
* @build JMapHeapConfigTest LingeredApp TmtoolTestScenario
|
||||
* @run main JMapHeapConfigTest
|
||||
*/
|
||||
import java.io.IOException;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import jdk.testlibrary.Utils;
|
||||
|
||||
public class JMapHeapConfigTest {
|
||||
|
||||
static final String expectedJMapValues[] = {
|
||||
"MinHeapFreeRatio",
|
||||
"MaxHeapFreeRatio",
|
||||
"MaxHeapSize",
|
||||
"NewSize",
|
||||
"MaxNewSize",
|
||||
"OldSize",
|
||||
"NewRatio",
|
||||
"SurvivorRatio",
|
||||
"MetaspaceSize",
|
||||
"CompressedClassSpaceSize",
|
||||
"G1HeapRegionSize"};
|
||||
|
||||
// ignoring MaxMetaspaceSize
|
||||
|
||||
private static Map<String, String> parseJMapOutput(List<String> jmapOutput) {
|
||||
Map<String, String> heapConfigMap = new HashMap<String, String>();
|
||||
boolean shouldParse = false;
|
||||
|
||||
for (String line : jmapOutput) {
|
||||
line = line.trim();
|
||||
|
||||
if (line.startsWith("Heap Configuration:")) {
|
||||
shouldParse = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (line.startsWith("Heap Usage:")) {
|
||||
shouldParse = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (shouldParse && !line.equals("")) {
|
||||
String[] lv = line.split("\\s+");
|
||||
try {
|
||||
heapConfigMap.put(lv[0], lv[2]);
|
||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
||||
// Ignore mailformed lines
|
||||
}
|
||||
}
|
||||
}
|
||||
return heapConfigMap;
|
||||
}
|
||||
|
||||
// Compare stored values
|
||||
private static void compareValues(Map<String, String> parsedJMapOutput, Map<String, String> parsedVmOutput) {
|
||||
for (String key : expectedJMapValues) {
|
||||
try {
|
||||
String jmapVal = parsedJMapOutput.get(key);
|
||||
if (jmapVal == null) {
|
||||
throw new RuntimeException("Key '" + key + "' doesn't exists in jmap output");
|
||||
}
|
||||
|
||||
String vmVal = parsedVmOutput.get(key);
|
||||
if (vmVal == null) {
|
||||
throw new RuntimeException("Key '" + key + "' doesn't exists in vm output");
|
||||
}
|
||||
|
||||
if (new BigDecimal(jmapVal).compareTo(new BigDecimal(vmVal)) != 0) {
|
||||
throw new RuntimeException(String.format("Key %s doesn't match %s vs %s", key, vmVal, jmapVal));
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
throw new RuntimeException("Unexpected key '" + key + "' value", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Starting JMapHeapConfigTest");
|
||||
|
||||
// Forward vm options to LingeredApp
|
||||
ArrayList<String> cmd = new ArrayList();
|
||||
cmd.addAll(Utils.getVmOptions());
|
||||
cmd.add("-XX:+PrintFlagsFinal");
|
||||
|
||||
TmtoolTestScenario tmt = TmtoolTestScenario.create("jmap", "-heap");
|
||||
int exitcode = tmt.launch(cmd);
|
||||
if (exitcode != 0) {
|
||||
throw new RuntimeException("Test FAILED jmap exits with non zero exit code " + exitcode);
|
||||
}
|
||||
|
||||
Map<String,String> parsedJmapOutput = parseJMapOutput(tmt.getToolOutput());
|
||||
Map<String,String> parsedVMOutput = tmt.parseFlagsFinal();
|
||||
|
||||
compareValues(parsedJmapOutput, parsedVMOutput);
|
||||
|
||||
// If test fails it throws RuntimeException
|
||||
System.out.println("Test PASSED");
|
||||
}
|
||||
}
|
||||
402
jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java
Normal file
402
jdk/test/sun/tools/jmap/heapconfig/LingeredApp.java
Normal file
@ -0,0 +1,402 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.nio.file.attribute.BasicFileAttributes;
|
||||
import java.nio.file.attribute.FileTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* This is a framework to launch an app that could be synchronized with caller
|
||||
* to make further attach actions reliable across supported platforms
|
||||
|
||||
* Caller example:
|
||||
* SmartTestApp a = SmartTestApp.startApp(cmd);
|
||||
* // do something
|
||||
* a.stopApp();
|
||||
*
|
||||
* or fine grained control
|
||||
*
|
||||
* a = new SmartTestApp("MyLock.lck");
|
||||
* a.createLock();
|
||||
* a.runApp();
|
||||
* a.waitAppReady();
|
||||
* // do something
|
||||
* a.deleteLock();
|
||||
* a.waitAppTerminate();
|
||||
*
|
||||
* Then you can work with app output and process object
|
||||
*
|
||||
* output = a.getAppOutput();
|
||||
* process = a.getProcess();
|
||||
*
|
||||
*/
|
||||
public class LingeredApp {
|
||||
|
||||
private static final long spinDelay = 1000;
|
||||
|
||||
private final String lockFileName;
|
||||
private long lockCreationTime;
|
||||
private Process appProcess;
|
||||
private final ArrayList<String> storedAppOutput;
|
||||
|
||||
/*
|
||||
* Drain child process output, store it into string array
|
||||
*/
|
||||
class InputGobbler extends Thread {
|
||||
|
||||
InputStream is;
|
||||
List<String> astr;
|
||||
|
||||
InputGobbler(InputStream is, List<String> astr) {
|
||||
this.is = is;
|
||||
this.astr = astr;
|
||||
}
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
InputStreamReader isr = new InputStreamReader(is);
|
||||
BufferedReader br = new BufferedReader(isr);
|
||||
String line = null;
|
||||
while ((line = br.readLine()) != null) {
|
||||
astr.add(line);
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create LingeredApp object on caller side. Lock file have be a valid filename
|
||||
* at writable location
|
||||
*
|
||||
* @param lockFileName - the name of lock file
|
||||
*/
|
||||
public LingeredApp(String lockFileName) {
|
||||
this.lockFileName = lockFileName;
|
||||
this.storedAppOutput = new ArrayList();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return name of lock file
|
||||
*/
|
||||
public String getLockFileName() {
|
||||
return this.lockFileName;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return name of testapp
|
||||
*/
|
||||
public String getAppName() {
|
||||
return this.getClass().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return pid of java process running testapp
|
||||
*/
|
||||
public long getPid() {
|
||||
if (appProcess == null) {
|
||||
throw new RuntimeException("Process is not alive");
|
||||
}
|
||||
return appProcess.getPid();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return process object
|
||||
*/
|
||||
public Process getProcess() {
|
||||
return appProcess;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return application output as string array. Empty array if application produced no output
|
||||
*/
|
||||
List<String> getAppOutput() {
|
||||
if (appProcess.isAlive()) {
|
||||
throw new RuntimeException("Process is still alive. Can't get its output.");
|
||||
}
|
||||
return storedAppOutput;
|
||||
}
|
||||
|
||||
/* Make sure all part of the app use the same method to get dates,
|
||||
as different methods could produce different results
|
||||
*/
|
||||
private static long epoch() {
|
||||
return new Date().getTime();
|
||||
}
|
||||
|
||||
private static long lastModified(String fileName) throws IOException {
|
||||
Path path = Paths.get(fileName);
|
||||
BasicFileAttributes attr = Files.readAttributes(path, BasicFileAttributes.class);
|
||||
return attr.lastModifiedTime().toMillis();
|
||||
}
|
||||
|
||||
private static void setLastModified(String fileName, long newTime) throws IOException {
|
||||
Path path = Paths.get(fileName);
|
||||
FileTime fileTime = FileTime.fromMillis(newTime);
|
||||
Files.setLastModifiedTime(path, fileTime);
|
||||
}
|
||||
|
||||
/**
|
||||
* create lock
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void createLock() throws IOException {
|
||||
Path path = Paths.get(lockFileName);
|
||||
// Files.deleteIfExists(path);
|
||||
Files.createFile(path);
|
||||
lockCreationTime = lastModified(lockFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete lock
|
||||
*
|
||||
* @throws IOException
|
||||
*/
|
||||
public void deleteLock() throws IOException {
|
||||
try {
|
||||
Path path = Paths.get(lockFileName);
|
||||
Files.delete(path);
|
||||
} catch (NoSuchFileException ex) {
|
||||
// Lock already deleted. Ignore error
|
||||
}
|
||||
}
|
||||
|
||||
public void waitAppTerminate() {
|
||||
while (true) {
|
||||
try {
|
||||
appProcess.waitFor();
|
||||
break;
|
||||
} catch (InterruptedException ex) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The app touches the lock file when it's started
|
||||
* wait while it happens. Caller have to delete lock on wait error.
|
||||
*
|
||||
* @param timeout
|
||||
* @throws java.io.IOException
|
||||
*/
|
||||
public void waitAppReady(long timeout) throws IOException {
|
||||
long here = epoch();
|
||||
while (true) {
|
||||
long epoch = epoch();
|
||||
if (epoch - here > (timeout * 1000)) {
|
||||
throw new IOException("App waiting timeout");
|
||||
}
|
||||
|
||||
// Live process should touch lock file every second
|
||||
long lm = lastModified(lockFileName);
|
||||
if (lm > lockCreationTime) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Make sure process didn't already exit
|
||||
if (!appProcess.isAlive()) {
|
||||
throw new IOException("App exited unexpectedly with " + appProcess.exitValue());
|
||||
}
|
||||
|
||||
try {
|
||||
Thread.sleep(spinDelay);
|
||||
} catch (InterruptedException ex) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the app
|
||||
*
|
||||
* @param vmArguments
|
||||
* @throws IOException
|
||||
*/
|
||||
public void runApp(List<String> vmArguments)
|
||||
throws IOException {
|
||||
|
||||
// We should always use testjava or throw an exception,
|
||||
// so we can't use JDKToolFinder.getJDKTool("java");
|
||||
// that falls back to compile java on error
|
||||
String jdkPath = System.getProperty("test.jdk");
|
||||
if (jdkPath == null) {
|
||||
// we are not under jtreg, try env
|
||||
Map<String, String> env = System.getenv();
|
||||
jdkPath = env.get("TESTJAVA");
|
||||
}
|
||||
|
||||
if (jdkPath == null) {
|
||||
throw new RuntimeException("Can't determine jdk path neither test.jdk property no TESTJAVA env are set");
|
||||
}
|
||||
|
||||
String osname = System.getProperty("os.name");
|
||||
String javapath = jdkPath + ((osname.startsWith("window")) ? "/bin/java.exe" : "/bin/java");
|
||||
|
||||
List<String> cmd = new ArrayList();
|
||||
cmd.add(javapath);
|
||||
|
||||
|
||||
if (vmArguments == null) {
|
||||
// Propagate test.vm.options to LingeredApp, filter out possible empty options
|
||||
String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
|
||||
for (String s : testVmOpts) {
|
||||
if (!s.equals("")) {
|
||||
cmd.add(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
// Lets user manage LingerApp options
|
||||
cmd.addAll(vmArguments);
|
||||
}
|
||||
|
||||
// Make sure we set correct classpath to run the app
|
||||
cmd.add("-cp");
|
||||
String classpath = System.getProperty("test.class.path");
|
||||
cmd.add((classpath == null) ? "." : classpath);
|
||||
|
||||
cmd.add(this.getAppName());
|
||||
cmd.add(lockFileName);
|
||||
|
||||
// Reporting
|
||||
StringBuilder cmdLine = new StringBuilder();
|
||||
for (String strCmd : cmd) {
|
||||
cmdLine.append("'").append(strCmd).append("' ");
|
||||
}
|
||||
|
||||
// A bit of verbosity
|
||||
System.out.println("Command line: [" + cmdLine.toString() + "]");
|
||||
|
||||
ProcessBuilder pb = new ProcessBuilder(cmd);
|
||||
// we don't expect any error output but make sure we are not stuck on pipe
|
||||
// pb.redirectErrorStream(false);
|
||||
pb.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
|
||||
appProcess = pb.start();
|
||||
|
||||
// Create pipe reader for process, and read stdin and stderr to array of strings
|
||||
InputGobbler gb = new InputGobbler(appProcess.getInputStream(), storedAppOutput);
|
||||
gb.start();
|
||||
}
|
||||
|
||||
/**
|
||||
* High level interface for test writers
|
||||
*/
|
||||
/**
|
||||
* Factory method that creates SmartAppTest object with ready to use application
|
||||
* lock name is autogenerated, wait timeout is hardcoded
|
||||
* @param cmd - vm options, could be null to auto add testvm.options
|
||||
* @return LingeredApp object
|
||||
* @throws IOException
|
||||
*/
|
||||
public static LingeredApp startApp(List<String> cmd) throws IOException {
|
||||
final String lockName = UUID.randomUUID().toString() + ".lck";
|
||||
final int waitTime = 10;
|
||||
|
||||
LingeredApp a = new LingeredApp(lockName);
|
||||
a.createLock();
|
||||
try {
|
||||
a.runApp(cmd);
|
||||
a.waitAppReady(waitTime);
|
||||
} catch (Exception ex) {
|
||||
a.deleteLock();
|
||||
throw ex;
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
public static LingeredApp startApp() throws IOException {
|
||||
return startApp(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete lock file that signal app to terminate, then
|
||||
* waits until app is actually terminated.
|
||||
* @throws IOException
|
||||
*/
|
||||
public void stopApp() throws IOException {
|
||||
deleteLock();
|
||||
waitAppTerminate();
|
||||
int exitcode = appProcess.exitValue();
|
||||
if (exitcode != 0) {
|
||||
throw new IOException("LingeredApp terminated with non-zero exit code " + exitcode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This part is the application it self
|
||||
*/
|
||||
public static void main(String args[]) {
|
||||
|
||||
if (args.length != 1) {
|
||||
System.err.println("Lock file name is not specified");
|
||||
System.exit(7);
|
||||
}
|
||||
|
||||
String theLockFileName = args[0];
|
||||
|
||||
try {
|
||||
Path path = Paths.get(theLockFileName);
|
||||
|
||||
while (Files.exists(path)) {
|
||||
long lm = lastModified(theLockFileName);
|
||||
long now = epoch();
|
||||
|
||||
// A bit of paranoja, don't allow test app to run more than an hour
|
||||
if (now - lm > 3600) {
|
||||
throw new IOException("Lock is too old. Aborting");
|
||||
}
|
||||
|
||||
// Touch lock to indicate our rediness
|
||||
setLastModified(theLockFileName, now);
|
||||
Thread.sleep(spinDelay);
|
||||
}
|
||||
|
||||
} catch (Exception ex) {
|
||||
System.err.println("LingeredApp ERROR: " + ex);
|
||||
// Leave exit_code = 1 to Java launcher
|
||||
System.exit(3);
|
||||
}
|
||||
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
72
jdk/test/sun/tools/jmap/heapconfig/LingeredAppTest.java
Normal file
72
jdk/test/sun/tools/jmap/heapconfig/LingeredAppTest.java
Normal file
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @summary Unit test for LingeredApp
|
||||
* @compile LingeredAppTest.java
|
||||
* @compile LingeredApp.java
|
||||
* @run main LingeredAppTest
|
||||
*/
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
public class LingeredAppTest {
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
System.out.println("Starting LingeredApp with default parameters");
|
||||
|
||||
ArrayList<String> cmd = new ArrayList();
|
||||
|
||||
// Propagate test.vm.options to LingeredApp, filter out possible empty options
|
||||
String testVmOpts[] = System.getProperty("test.vm.opts","").split("\\s+");
|
||||
for (String s : testVmOpts) {
|
||||
if (!s.equals("")) {
|
||||
cmd.add(s);
|
||||
}
|
||||
}
|
||||
|
||||
cmd.add("-XX:+PrintFlagsFinal");
|
||||
|
||||
LingeredApp a = LingeredApp.startApp(cmd);
|
||||
System.out.printf("App pid: %d\n", a.getPid());
|
||||
a.stopApp();
|
||||
|
||||
System.out.println("App output:");
|
||||
int count = 0;
|
||||
for (String line : a.getAppOutput()) {
|
||||
count += 1;
|
||||
}
|
||||
System.out.println("Found " + count + " lines in VM output");
|
||||
System.out.println("Test PASSED");
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
System.out.println("Test ERROR");
|
||||
System.exit(3);
|
||||
}
|
||||
}
|
||||
}
|
||||
137
jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java
Normal file
137
jdk/test/sun/tools/jmap/heapconfig/TmtoolTestScenario.java
Normal file
@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.logging.Level;
|
||||
import java.util.logging.Logger;
|
||||
import jdk.testlibrary.JDKToolLauncher;
|
||||
import jdk.testlibrary.Utils;
|
||||
|
||||
public class TmtoolTestScenario {
|
||||
|
||||
private final ArrayList<String> toolOutput = new ArrayList();
|
||||
private LingeredApp theApp = null;
|
||||
private final String toolName;
|
||||
private final String[] toolArgs;
|
||||
|
||||
/**
|
||||
* @param toolName - name of tool to test
|
||||
* @param toolArgs - tool arguments
|
||||
* @return the object
|
||||
*/
|
||||
public static TmtoolTestScenario create(String toolName, String... toolArgs) {
|
||||
return new TmtoolTestScenario(toolName, toolArgs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return STDOUT of tool
|
||||
*/
|
||||
public List<String> getToolOutput() {
|
||||
return toolOutput;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return STDOUT of test app
|
||||
*/
|
||||
public List<String> getAppOutput() {
|
||||
return theApp.getAppOutput();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Value of the app output with -XX:+PrintFlagsFinal as a map.
|
||||
*/
|
||||
public Map<String, String> parseFlagsFinal() {
|
||||
List<String> astr = theApp.getAppOutput();
|
||||
Map<String, String> vmMap = new HashMap();
|
||||
|
||||
for (String line : astr) {
|
||||
String[] lv = line.trim().split("\\s+");
|
||||
try {
|
||||
vmMap.put(lv[1], lv[3]);
|
||||
} catch (ArrayIndexOutOfBoundsException ex) {
|
||||
// ignore mailformed lines
|
||||
}
|
||||
}
|
||||
return vmMap;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param vmArgs - vm and java arguments to launch test app
|
||||
* @return exit code of tool
|
||||
*/
|
||||
public int launch(List<String> vmArgs) {
|
||||
System.out.println("Starting LingeredApp");
|
||||
try {
|
||||
try {
|
||||
theApp = LingeredApp.startApp(vmArgs);
|
||||
|
||||
System.out.println("Starting " + toolName + " against " + theApp.getPid());
|
||||
JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(toolName);
|
||||
|
||||
for (String cmd : toolArgs) {
|
||||
launcher.addToolArg(cmd);
|
||||
}
|
||||
launcher.addToolArg(Long.toString(theApp.getPid()));
|
||||
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(launcher.getCommand());
|
||||
processBuilder.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
Process toolProcess = processBuilder.start();
|
||||
|
||||
// By default child process output stream redirected to pipe, so we are reading it in foreground.
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(toolProcess.getInputStream()));
|
||||
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
toolOutput.add(line.trim());
|
||||
}
|
||||
|
||||
toolProcess.waitFor();
|
||||
|
||||
return toolProcess.exitValue();
|
||||
} finally {
|
||||
theApp.stopApp();
|
||||
}
|
||||
} catch (IOException | InterruptedException ex) {
|
||||
throw new RuntimeException("Test ERROR " + ex, ex);
|
||||
}
|
||||
}
|
||||
|
||||
public void launch(String... appArgs) throws IOException {
|
||||
launch(Arrays.asList(appArgs));
|
||||
}
|
||||
|
||||
private TmtoolTestScenario(String toolName, String[] toolArgs) {
|
||||
this.toolName = toolName;
|
||||
this.toolArgs = toolArgs;
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user