This commit is contained in:
Lana Steuck 2015-01-29 15:35:29 -08:00
commit ce0c1fcc34
80 changed files with 4876 additions and 1605 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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), \

View File

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

View File

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

View File

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

View File

@ -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.
*/

View File

@ -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&trade; 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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

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

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

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

View 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
}

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

View File

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

View File

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

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

View File

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

View File

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

View File

@ -27,3 +27,9 @@
}
}
NOVAL.COM = {
empty1 =
empty2 =.
quote1 = "
quote2 = '
}

View File

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

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

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

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

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

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