diff --git a/.github/actions/get-jtreg/action.yml b/.github/actions/get-jtreg/action.yml index 03617e5fdb0..0ad40d395d3 100644 --- a/.github/actions/get-jtreg/action.yml +++ b/.github/actions/get-jtreg/action.yml @@ -1,5 +1,5 @@ # -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2023, 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 diff --git a/.github/workflows/build-macos.yml b/.github/workflows/build-macos.yml index 414c07a8080..4186c451b78 100644 --- a/.github/workflows/build-macos.yml +++ b/.github/workflows/build-macos.yml @@ -55,7 +55,7 @@ on: jobs: build-macos: name: build - runs-on: macos-11 + runs-on: macos-13 strategy: fail-fast: false diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 48009e8509d..48985dbcfe1 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,5 +1,5 @@ # -# Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2022, 2023, 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 @@ -162,7 +162,7 @@ jobs: run: | # On macOS we need to install some dependencies for testing brew install make - sudo xcode-select --switch /Applications/Xcode_11.7.app/Contents/Developer + sudo xcode-select --switch /Applications/Xcode_14.3.1.app/Contents/Developer # This will make GNU make available as 'make' and not only as 'gmake' echo '/usr/local/opt/make/libexec/gnubin' >> $GITHUB_PATH if: runner.os == 'macOS' && steps.check_if_run.outputs.should_run != 'false' diff --git a/.jcheck/conf b/.jcheck/conf index be7ad6d26f5..56362781209 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,10 +1,11 @@ [general] project=jdk-updates jbs=JDK -version=11.0.24 +version=11.0.25 [checks] -error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace +error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists +warning=issuestitle,binary [repository] tags=(?:jdk-(?:[1-9]([0-9]*)(?:\.(?:0|[1-9][0-9]*)){0,4})(?:\+(?:(?:[0-9]+))|(?:-ga)))|(?:jdk[4-9](?:u\d{1,3})?-(?:(?:b\d{2,3})|(?:ga)))|(?:hs\d\d(?:\.\d{1,2})?-b\d\d) @@ -29,3 +30,6 @@ role=committer [checks "issues"] pattern=^([124-8][0-9]{6}): (\S.*)$ + +[checks "problemlists"] +dirs=test/jdk|test/langtools|test/lib-test|test/hotspot/jtreg|test/jaxp diff --git a/make/RunTests.gmk b/make/RunTests.gmk index 2702e419547..9fb699bee04 100644 --- a/make/RunTests.gmk +++ b/make/RunTests.gmk @@ -749,7 +749,7 @@ define SetupRunJtregTestBody $$(RM) -r $$($1_TEST_RESULTS_DIR) $1_COMMAND_LINE := \ - $$(JAVA) $$($1_JTREG_LAUNCHER_OPTIONS) \ + $$(JTREG_JAVA) $$($1_JTREG_LAUNCHER_OPTIONS) \ -Dprogram=jtreg -jar $$(JT_HOME)/lib/jtreg.jar \ $$($1_JTREG_BASIC_OPTIONS) \ -testjdk:$$(JDK_IMAGE_DIR) \ diff --git a/make/RunTestsPrebuilt.gmk b/make/RunTestsPrebuilt.gmk index b5e00a70a8f..918140fb5dd 100644 --- a/make/RunTestsPrebuilt.gmk +++ b/make/RunTestsPrebuilt.gmk @@ -122,6 +122,7 @@ $(eval $(call SetupVariable,JT_HOME)) $(eval $(call SetupVariable,JDK_IMAGE_DIR,$(OUTPUTDIR)/images/jdk)) $(eval $(call SetupVariable,TEST_IMAGE_DIR,$(OUTPUTDIR)/images/test)) $(eval $(call SetupVariable,SYMBOLS_IMAGE_DIR,$(OUTPUTDIR)/images/symbols,NO_CHECK)) +$(eval $(call SetupVariable,JTREG_JDK,$(BOOT_JDK))) # Provide default values for tools that we need $(eval $(call SetupVariable,MAKE,make,NO_CHECK)) @@ -294,6 +295,7 @@ $(call CreateNewSpec, $(NEW_SPEC), \ TOPDIR := $(TOPDIR), \ OUTPUTDIR := $(OUTPUTDIR), \ BOOT_JDK := $(BOOT_JDK), \ + JTREG_JDK := $(JTREG_JDK), \ JT_HOME := $(JT_HOME), \ JDK_IMAGE_DIR := $(JDK_IMAGE_DIR), \ TEST_IMAGE_DIR := $(TEST_IMAGE_DIR), \ diff --git a/make/RunTestsPrebuiltSpec.gmk b/make/RunTestsPrebuiltSpec.gmk index eb6a91acf37..4fbd67be2d6 100644 --- a/make/RunTestsPrebuiltSpec.gmk +++ b/make/RunTestsPrebuiltSpec.gmk @@ -125,6 +125,8 @@ JAR := $(FIXPATH) $(JAR_CMD) JLINK := $(FIXPATH) $(JLINK_CMD) JMOD := $(FIXPATH) $(JMOD_CMD) +JTREG_JAVA := $(FIXPATH) $(JTREG_JDK)/bin/java $(JAVA_FLAGS_BIG) $(JAVA_FLAGS) + BUILD_JAVA := $(JDK_IMAGE_DIR)/bin/JAVA ################################################################################ # Some common tools. Assume most common name and no path. diff --git a/make/autoconf/compare.sh.in b/make/autoconf/compare.sh.in index 31468df8974..d0643f2b91a 100644 --- a/make/autoconf/compare.sh.in +++ b/make/autoconf/compare.sh.in @@ -39,6 +39,7 @@ export AWK="@AWK@" export BASH="@BASH@" export CAT="@CAT@" export CMP="@CMP@" +export CODESIGN="@CODESIGN@" export CP="@CP@" export CUT="@CUT@" export DIFF="@DIFF@" diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index 6a6db9089eb..8ea0b339c1c 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -196,6 +196,7 @@ AC_DEFUN([FLAGS_SETUP_WARNINGS], clang) DISABLE_WARNING_PREFIX="-Wno-" + BUILD_CC_DISABLE_WARNING_PREFIX="-Wno-" CFLAGS_WARNINGS_ARE_ERRORS="-Werror" WARNINGS_ENABLE_ALL="-Wall -Wextra -Wformat=2" diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4 index 5e7fab4a8aa..f588ce35b54 100644 --- a/make/autoconf/lib-tests.m4 +++ b/make/autoconf/lib-tests.m4 @@ -145,12 +145,47 @@ AC_DEFUN_ONCE([LIB_TESTS_SETUP_JTREG], UTIL_FIXUP_PATH(JT_HOME) AC_SUBST(JT_HOME) + # Specify a JDK for running jtreg. Defaults to the BOOT_JDK. + AC_ARG_WITH(jtreg-jdk, [AS_HELP_STRING([--with-jdk], + [path to JDK for running jtreg @<:@BOOT_JDK@:>@])]) + + AC_MSG_CHECKING([for jtreg jdk]) + if test "x${with_jtreg_jdk}" != x; then + if test "x${with_jtreg_jdk}" = xno; then + AC_MSG_RESULT([no, jtreg jdk not specified]) + elif test "x${with_jtreg_jdk}" = xyes; then + AC_MSG_RESULT([not specified]) + AC_MSG_ERROR([--with-jtreg-jdk needs a value]) + else + JTREG_JDK="${with_jtreg_jdk}" + AC_MSG_RESULT([$JTREG_JDK]) + UTIL_FIXUP_PATH(JTREG_JDK) + if test ! -f "$JTREG_JDK/bin/java"; then + AC_MSG_ERROR([Could not find jtreg java at $JTREG_JDK/bin/java]) + fi + fi + else + JTREG_JDK="${BOOT_JDK}" + AC_MSG_RESULT([no, using BOOT_JDK]) + fi + + UTIL_FIXUP_PATH(JTREG_JDK) + AC_SUBST([JTREG_JDK]) + # For use in the configure script + JTREG_JAVA="$FIXPATH $JTREG_JDK/bin/java" + # Verify jtreg version if test "x$JT_HOME" != x; then + AC_MSG_CHECKING([jtreg jar existence]) + if test ! -f "$JT_HOME/lib/jtreg.jar"; then + AC_MSG_ERROR([Could not find jtreg jar at $JT_HOME/lib/jtreg.jar]) + fi + AC_MSG_CHECKING([jtreg version number]) # jtreg -version looks like this: "jtreg 6.1+1-19" # Extract actual version part ("6.1" in this case) - jtreg_version_full=`$JAVA -jar $JT_HOME/lib/jtreg.jar -version | $HEAD -n 1 | $CUT -d ' ' -f 2` + jtreg_version_full=$($JTREG_JAVA -jar $JT_HOME/lib/jtreg.jar -version | $HEAD -n 1 | $CUT -d ' ' -f 2) + jtreg_version=${jtreg_version_full/%+*} AC_MSG_RESULT([$jtreg_version]) diff --git a/make/autoconf/libraries.m4 b/make/autoconf/libraries.m4 index 823a0632470..b94165aa157 100644 --- a/make/autoconf/libraries.m4 +++ b/make/autoconf/libraries.m4 @@ -159,7 +159,7 @@ AC_DEFUN_ONCE([LIB_SETUP_LIBRARIES], if test "x$OPENJDK_TARGET_OS" = xwindows; then BASIC_JVM_LIBS="$BASIC_JVM_LIBS kernel32.lib user32.lib gdi32.lib winspool.lib \ comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib \ - wsock32.lib winmm.lib version.lib psapi.lib" + ws2_32.lib winmm.lib version.lib psapi.lib" fi JDKLIB_LIBS="$BASIC_JDKLIB_LIBS" diff --git a/make/autoconf/spec.gmk.in b/make/autoconf/spec.gmk.in index 34a056ea63e..e6828baa0ad 100644 --- a/make/autoconf/spec.gmk.in +++ b/make/autoconf/spec.gmk.in @@ -652,6 +652,9 @@ SJAVAC_SERVER_JAVA = $(SJAVAC_SERVER_JAVA_CMD) \ # overriding that value by using ?=. JAVAC_FLAGS? = @JAVAC_FLAGS@ +JTREG_JDK := @JTREG_JDK@ +JTREG_JAVA = @FIXPATH@ $(JTREG_JDK)/bin/java $(JAVA_FLAGS_BIG) $(JAVA_FLAGS) + BUILD_JAVA_FLAGS := @BOOTCYCLE_JVM_ARGS_BIG@ BUILD_JAVA=@FIXPATH@ $(BUILD_JDK)/bin/java $(BUILD_JAVA_FLAGS) BUILD_JAR=@FIXPATH@ $(BUILD_JDK)/bin/jar diff --git a/make/autoconf/version-numbers b/make/autoconf/version-numbers index d6b92cdb115..fe5e0d9850f 100644 --- a/make/autoconf/version-numbers +++ b/make/autoconf/version-numbers @@ -28,12 +28,12 @@ DEFAULT_VERSION_FEATURE=11 DEFAULT_VERSION_INTERIM=0 -DEFAULT_VERSION_UPDATE=24 +DEFAULT_VERSION_UPDATE=25 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2024-07-16 +DEFAULT_VERSION_DATE=2024-10-15 DEFAULT_VERSION_CLASSFILE_MAJOR=55 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_ACCEPTABLE_BOOT_VERSIONS="10 11" diff --git a/make/data/cacerts/ssltlsrootecc2022 b/make/data/cacerts/ssltlsrootecc2022 new file mode 100644 index 00000000000..706e6aefb4e --- /dev/null +++ b/make/data/cacerts/ssltlsrootecc2022 @@ -0,0 +1,21 @@ +Owner: CN=SSL.com TLS ECC Root CA 2022, O=SSL Corporation, C=US +Issuer: CN=SSL.com TLS ECC Root CA 2022, O=SSL Corporation, C=US +Serial number: 1403f5abfb378b17405be243b2a5d1c4 +Valid from: Thu Aug 25 16:33:48 GMT 2022 until: Sun Aug 19 16:33:47 GMT 2046 +Signature algorithm name: SHA384withECDSA +Subject Public Key Algorithm: 384-bit EC (secp384r1) key +Version: 3 +-----BEGIN CERTIFICATE----- +MIICOjCCAcCgAwIBAgIQFAP1q/s3ixdAW+JDsqXRxDAKBggqhkjOPQQDAzBOMQsw +CQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQDDBxT +U0wuY29tIFRMUyBFQ0MgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzM0OFoXDTQ2 +MDgxOTE2MzM0N1owTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jwb3Jh +dGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgRUNDIFJvb3QgQ0EgMjAyMjB2MBAG +ByqGSM49AgEGBSuBBAAiA2IABEUpNXP6wrgjzhR9qLFNoFs27iosU8NgCTWyJGYm +acCzldZdkkAZDsalE3D07xJRKF3nzL35PIXBz5SQySvOkkJYWWf9lCcQZIxPBLFN +SeR7T5v15wj4A4j3p8OSSxlUgaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSME +GDAWgBSJjy+j6CugFFR781a4Jl9nOAuc0DAdBgNVHQ4EFgQUiY8vo+groBRUe/NW +uCZfZzgLnNAwDgYDVR0PAQH/BAQDAgGGMAoGCCqGSM49BAMDA2gAMGUCMFXjIlbp +15IkWE8elDIPDAI2wv2sdDJO4fscgIijzPvX6yv/N33w7deedWo1dlJF4AIxAMeN +b0Igj762TVntd00pxCAgRWSGOlDGxK0tk/UYfXLtqc/ErFc2KAhl3zx5Zn6g6g== +-----END CERTIFICATE----- diff --git a/make/data/cacerts/ssltlsrootrsa2022 b/make/data/cacerts/ssltlsrootrsa2022 new file mode 100644 index 00000000000..ad456b0b5f4 --- /dev/null +++ b/make/data/cacerts/ssltlsrootrsa2022 @@ -0,0 +1,39 @@ +Owner: CN=SSL.com TLS RSA Root CA 2022, O=SSL Corporation, C=US +Issuer: CN=SSL.com TLS RSA Root CA 2022, O=SSL Corporation, C=US +Serial number: 6fbedaad73bd0840e28b4dbed4f75b91 +Valid from: Thu Aug 25 16:34:22 GMT 2022 until: Sun Aug 19 16:34:21 GMT 2046 +Signature algorithm name: SHA256withRSA +Subject Public Key Algorithm: 4096-bit RSA key +Version: 3 +-----BEGIN CERTIFICATE----- +MIIFiTCCA3GgAwIBAgIQb77arXO9CEDii02+1PdbkTANBgkqhkiG9w0BAQsFADBO +MQswCQYDVQQGEwJVUzEYMBYGA1UECgwPU1NMIENvcnBvcmF0aW9uMSUwIwYDVQQD +DBxTU0wuY29tIFRMUyBSU0EgUm9vdCBDQSAyMDIyMB4XDTIyMDgyNTE2MzQyMloX +DTQ2MDgxOTE2MzQyMVowTjELMAkGA1UEBhMCVVMxGDAWBgNVBAoMD1NTTCBDb3Jw +b3JhdGlvbjElMCMGA1UEAwwcU1NMLmNvbSBUTFMgUlNBIFJvb3QgQ0EgMjAyMjCC +AiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANCkCXJPQIgSYT41I57u9nTP +L3tYPc48DRAokC+X94xI2KDYJbFMsBFMF3NQ0CJKY7uB0ylu1bUJPiYYf7ISf5OY +t6/wNr/y7hienDtSxUcZXXTzZGbVXcdotL8bHAajvI9AI7YexoS9UcQbOcGV0ins +S657Lb85/bRi3pZ7QcacoOAGcvvwB5cJOYF0r/c0WRFXCsJbwST0MXMwgsadugL3 +PnxEX4MN8/HdIGkWCVDi1FW24IBydm5MR7d1VVm0U3TZlMZBrViKMWYPHqIbKUBO +L9975hYsLfy/7PO0+r4Y9ptJ1O4Fbtk085zx7AGL0SDGD6C1vBdOSHtRwvzpXGk3 +R2azaPgVKPC506QVzFpPulJwoxJF3ca6TvvC0PeoUidtbnm1jPx7jMEWTO6Af77w +dr5BUxIzrlo4QqvXDz5BjXYHMtWrifZOZ9mxQnUjbvPNQrL8VfVThxc7wDNY8VLS ++YCk8OjwO4s4zKTGkH8PnP2L0aPP2oOnaclQNtVcBdIKQXTbYxE3waWglksejBYS +d66UNHsef8JmAOSqg+qKkK3ONkRN0VHpvB/zagX9wHQfJRlAUW7qglFA35u5CCoG +AtUjHBPW6dvbxrB6y3snm/vg1UYk7RBLY0ulBY+6uB0rpvqR4pJSvezrZ5dtmi2f +gTIFZzL7SAg/2SW4BCUvAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j +BBgwFoAU+y437uOEeicuzRk1sTN8/9REQrkwHQYDVR0OBBYEFPsuN+7jhHonLs0Z +NbEzfP/UREK5MA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEAjYlt +hEUY8U+zoO9opMAdrDC8Z2awms22qyIZZtM7QbUQnRC6cm4pJCAcAZli05bg4vsM +QtfhWsSWTVTNj8pDU/0quOr4ZcoBwq1gaAafORpR2eCNJvkLTqVTJXojpBzOCBvf +R4iyrT7gJ4eLSYwfqUdYe5byiB0YrrPRpgqU+tvT5TgKa3kSM/tKWTcWQA673vWJ +DPFs0/dRa1419dvAJuoSc06pkZCmF8NsLzjUo3KUQyxi4U5cMj29TH0ZR6LDSeeW +P4+a0zvkEdiLA9z2tmBVGKaBUfPhqBVq6+AL8BQx1rmMRTqoENjwuSfr98t67wVy +lrXEj5ZzxOhWc5y8aVFjvO9nHEMaX3cZHxj4HCUp+UmZKbaSPaKDN7EgkaibMOlq +bLQjk2UEqxHzDh1TJElTHaE/nUiSEeJ9DU/1172iWD54nR4fK/4huxoTtrEoZP2w +AgDHbICivRZQIA9ygV/MlP+7mea6kMvq+cYMwq7FGc4zoWtcu358NFcXrfA/rs3q +r5nsLFR+jM4uElZI7xc7P0peYNLcdDa8pUNjyw9bowJWCZ4kLOGGgYz+qxcs+sji +Mho6/4UIyYOf8kpIEFR3N+2ivEC+5BB09+Rbu7nzifmPQdjH5FCQNYA+HLhNkNPU +98OwoX6EyneSMSy4kLGCenROmxMmtNVQZlR4rmA= +-----END CERTIFICATE----- diff --git a/make/data/currency/CurrencyData.properties b/make/data/currency/CurrencyData.properties index 26f4aa24d88..550662ec38a 100644 --- a/make/data/currency/CurrencyData.properties +++ b/make/data/currency/CurrencyData.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 2024, 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 @@ -32,7 +32,7 @@ formatVersion=3 # Version of the currency code information in this class. # It is a serial number that accompanies with each amendment. -dataVersion=176 +dataVersion=177 # List of all valid ISO 4217 currency codes. # To ensure compatibility, do not remove codes. @@ -56,8 +56,8 @@ all=ADP020-AED784-AFA004-AFN971-ALL008-AMD051-ANG532-AOA973-ARS032-ATS040-AUD036 TPE626-TRL792-TRY949-TTD780-TWD901-TZS834-UAH980-UGX800-USD840-USN997-USS998-UYI940-\ UYU858-UZS860-VEB862-VED926-VEF937-VES928-VND704-VUV548-WST882-XAF950-XAG961-XAU959-XBA955-\ XBB956-XBC957-XBD958-XCD951-XCG532-XDR960-XFO000-XFU000-XOF952-XPD964-XPF953-\ - XPT962-XSU994-XTS963-XUA965-XXX999-YER886-YUM891-ZAR710-ZMK894-ZMW967-ZWD716-ZWL932-\ - ZWN942-ZWR935 + XPT962-XSU994-XTS963-XUA965-XXX999-YER886-YUM891-ZAR710-ZMK894-ZMW967-ZWD716-ZWG924-\ + ZWL932-ZWN942-ZWR935 # Mappings from ISO 3166 country codes to ISO 4217 currency codes. @@ -582,7 +582,7 @@ YE=YER # ZAMBIA ZM=ZMW # ZIMBABWE -ZW=ZWL +ZW=ZWG # List of currencies with non-2digit decimals for minor units, diff --git a/make/data/lsrdata/language-subtag-registry.txt b/make/data/lsrdata/language-subtag-registry.txt index c6937ee80f1..3079d77ed8b 100644 --- a/make/data/lsrdata/language-subtag-registry.txt +++ b/make/data/lsrdata/language-subtag-registry.txt @@ -1,4 +1,4 @@ -File-Date: 2023-10-16 +File-Date: 2024-06-14 %% Type: language Subtag: aa @@ -882,6 +882,7 @@ Type: language Subtag: sa Description: Sanskrit Added: 2005-10-16 +Scope: macrolanguage %% Type: language Subtag: sc @@ -8028,6 +8029,12 @@ Description: Lowland Oaxaca Chontal Added: 2009-07-29 %% Type: language +Subtag: cls +Description: Classical Sanskrit +Added: 2024-03-04 +Macrolanguage: sa +%% +Type: language Subtag: clt Description: Lautu Chin Added: 2012-08-12 @@ -9395,6 +9402,7 @@ Macrolanguage: doi %% Type: language Subtag: dgr +Description: Tlicho Description: Dogrib Description: Tłı̨chǫ Added: 2005-10-16 @@ -15248,6 +15256,11 @@ Description: Isu (Menchum Division) Added: 2009-07-29 %% Type: language +Subtag: isv +Description: Interslavic +Added: 2024-05-15 +%% +Type: language Subtag: itb Description: Binongan Itneg Added: 2009-07-29 @@ -30916,6 +30929,11 @@ Description: Ririo Added: 2009-07-29 %% Type: language +Subtag: rrm +Description: Moriori +Added: 2024-03-04 +%% +Type: language Subtag: rro Description: Waima Added: 2009-07-29 @@ -37660,6 +37678,12 @@ Description: Venezuelan Sign Language Added: 2009-07-29 %% Type: language +Subtag: vsn +Description: Vedic Sanskrit +Added: 2024-03-04 +Macrolanguage: sa +%% +Type: language Subtag: vsv Description: Valencian Sign Language Description: Llengua de signes valenciana @@ -47559,6 +47583,13 @@ Comments: Aluku dialect of the "Busi Nenge Tongo" English-based Creole continuum in Eastern Suriname and Western French Guiana %% Type: variant +Subtag: anpezo +Description: Anpezo standard of Ladin +Added: 2024-03-04 +Prefix: lld +Comments: Represents the standard written form of Ladin in Anpezo +%% +Type: variant Subtag: ao1990 Description: Portuguese Language Orthographic Agreement of 1990 (Acordo Ortográfico da Língua Portuguesa de 1990) @@ -47779,6 +47810,22 @@ Added: 2012-02-05 Prefix: en %% Type: variant +Subtag: fascia +Description: Fascia standard of Ladin +Added: 2024-03-04 +Prefix: lld +Comments: Represents the standard written form of Ladin in Fascia which + unified the three subvarieties Cazet, Brach and Moenat +%% +Type: variant +Subtag: fodom +Description: Fodom standard of Ladin +Added: 2024-03-04 +Prefix: lld +Comments: Represents the standard written form of Ladin in Livinallongo + and Colle Santa Lucia +%% +Type: variant Subtag: fonipa Description: International Phonetic Alphabet Added: 2006-12-11 @@ -47819,6 +47866,13 @@ Prefix: oc Comments: Occitan variant spoken in Gascony %% Type: variant +Subtag: gherd +Description: Gherdëina standard of Ladin +Added: 2024-03-04 +Prefix: lld +Comments: Represents the standard written form of Ladin in Gherdëina +%% +Type: variant Subtag: grclass Description: Classical Occitan orthography Added: 2018-04-22 @@ -47955,7 +48009,9 @@ Type: variant Subtag: laukika Description: Classical Sanskrit Added: 2010-07-28 +Deprecated: 2024-06-08 Prefix: sa +Comments: Preferred tag is cls %% Type: variant Subtag: lemosin @@ -48120,6 +48176,15 @@ Comments: Peano’s Interlingua, created in 1903 by Giuseppe Peano as an Added: 2020-03-12 %% Type: variant +Subtag: pehoeji +Description: Hokkien Vernacular Romanization System +Description: Pe̍h-ōe-jī orthography/romanization +Added: 2024-03-04 +Prefix: nan-Latn +Comments: Modern Hokkien Vernacular Romanization System, evolved from + the New Dictionary in the Amoy by John Van Nest Talmage in 1894 +%% +Type: variant Subtag: petr1708 Description: Petrine orthography Added: 2010-10-10 @@ -48254,6 +48319,16 @@ Added: 2021-07-17 Prefix: da %% Type: variant +Subtag: tailo +Description: Taiwanese Hokkien Romanization System for Hokkien + languages +Description: Tâi-lô orthography/romanization +Added: 2024-03-04 +Prefix: nan-Latn +Comments: Taiwanese Hokkien Romanization System (Tâi-lô) published in + 2006 by the Taiwan Ministry of Education +%% +Type: variant Subtag: tarask Description: Belarusian in Taraskievica orthography Added: 2007-04-27 @@ -48312,9 +48387,20 @@ Type: variant Subtag: vaidika Description: Vedic Sanskrit Added: 2010-07-28 +Deprecated: 2024-06-08 Prefix: sa Comments: The most ancient dialect of Sanskrit used in verse and prose composed until about the 4th century B.C.E. +Comments: Preferred tag is vsn +%% +Type: variant +Subtag: valbadia +Description: Val Badia standard of Ladin +Added: 2024-03-04 +Prefix: lld +Comments: Represents the standard written form of Ladin in the Val + Badia, unifying the three variants Marô, Mesaval and Badiot spoken + in this valley %% Type: variant Subtag: valencia diff --git a/make/scripts/compare.sh b/make/scripts/compare.sh index a2f6cbc4d88..b6b7f1f33b9 100644 --- a/make/scripts/compare.sh +++ b/make/scripts/compare.sh @@ -42,6 +42,7 @@ if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then LDD_CMD="$OTOOL -L" DIS_CMD="$OTOOL -v -V -t" STAT_PRINT_SIZE="-f %z" + STRIP="$STRIP -no_code_signature_warning" elif [ "$OPENJDK_TARGET_OS" = "windows" ]; then FULLDUMP_CMD="$DUMPBIN -all" LDD_CMD="$DUMPBIN -dependents" @@ -638,14 +639,22 @@ compare_bin_file() { ORIG_THIS_FILE="$THIS_FILE" ORIG_OTHER_FILE="$OTHER_FILE" - if [ "$STRIP_ALL" = "true" ] || [[ "$STRIP_BEFORE_COMPARE" = *"$BIN_FILE"* ]]; then + if [ "$STRIP_ALL" = "true" ] || [[ "$STRIP_BEFORE_COMPARE" = *"$BIN_FILE"* ]] \ + || [ "$OPENJDK_TARGET_OS" = "macosx" ]; then THIS_STRIPPED_FILE=$FILE_WORK_DIR/this/$NAME OTHER_STRIPPED_FILE=$FILE_WORK_DIR/other/$NAME $MKDIR -p $FILE_WORK_DIR/this $FILE_WORK_DIR/other $CP $THIS_FILE $THIS_STRIPPED_FILE $CP $OTHER_FILE $OTHER_STRIPPED_FILE - $STRIP $THIS_STRIPPED_FILE - $STRIP $OTHER_STRIPPED_FILE + if [ "$STRIP_ALL" = "true" ] || [[ "$STRIP_BEFORE_COMPARE" = *"$BIN_FILE"* ]]; then + $STRIP $THIS_STRIPPED_FILE + $STRIP $OTHER_STRIPPED_FILE + fi + # On macosx, always remove any signature before comparing + if [ "$OPENJDK_TARGET_OS" = "macosx" ]; then + $CODESIGN --remove-signature $THIS_STRIPPED_FILE + $CODESIGN --remove-signature $OTHER_STRIPPED_FILE + fi THIS_FILE="$THIS_STRIPPED_FILE" OTHER_FILE="$OTHER_STRIPPED_FILE" fi diff --git a/src/hotspot/os/aix/os_aix.inline.hpp b/src/hotspot/os/aix/os_aix.inline.hpp index 6688c551179..9a2522ab54e 100644 --- a/src/hotspot/os/aix/os_aix.inline.hpp +++ b/src/hotspot/os/aix/os_aix.inline.hpp @@ -142,10 +142,6 @@ inline int os::connect(int fd, struct sockaddr *him, socklen_t len) { RESTARTABLE_RETURN_INT(::connect(fd, him, len)); } -inline struct hostent* os::get_host_by_name(char* name) { - return ::gethostbyname(name); -} - inline bool os::supports_monotonic_clock() { // mread_real_time() is monotonic on AIX (see os::javaTimeNanos() comments) return true; diff --git a/src/hotspot/os/bsd/os_bsd.inline.hpp b/src/hotspot/os/bsd/os_bsd.inline.hpp index dcbea055a87..285adfecaf2 100644 --- a/src/hotspot/os/bsd/os_bsd.inline.hpp +++ b/src/hotspot/os/bsd/os_bsd.inline.hpp @@ -144,10 +144,6 @@ inline int os::connect(int fd, struct sockaddr* him, socklen_t len) { RESTARTABLE_RETURN_INT(::connect(fd, him, len)); } -inline struct hostent* os::get_host_by_name(char* name) { - return ::gethostbyname(name); -} - inline bool os::supports_monotonic_clock() { #ifdef __APPLE__ return true; diff --git a/src/hotspot/os/linux/os_linux.inline.hpp b/src/hotspot/os/linux/os_linux.inline.hpp index 89411654159..803792566e7 100644 --- a/src/hotspot/os/linux/os_linux.inline.hpp +++ b/src/hotspot/os/linux/os_linux.inline.hpp @@ -136,10 +136,6 @@ inline int os::connect(int fd, struct sockaddr* him, socklen_t len) { RESTARTABLE_RETURN_INT(::connect(fd, him, len)); } -inline struct hostent* os::get_host_by_name(char* name) { - return ::gethostbyname(name); -} - inline bool os::supports_monotonic_clock() { return Linux::_clock_gettime != NULL; } diff --git a/src/hotspot/os/linux/os_perf_linux.cpp b/src/hotspot/os/linux/os_perf_linux.cpp index 83dc3c9e92f..d0571e51ab9 100644 --- a/src/hotspot/os/linux/os_perf_linux.cpp +++ b/src/hotspot/os/linux/os_perf_linux.cpp @@ -837,7 +837,7 @@ SystemProcessInterface::SystemProcesses::ProcessIterator::ProcessIterator() { bool SystemProcessInterface::SystemProcesses::ProcessIterator::initialize() { _dir = os::opendir("/proc"); _entry = NULL; - _valid = true; + _valid = _dir != NULL; // May be null if /proc is not accessible. next_process(); return true; diff --git a/src/hotspot/os/solaris/os_solaris.inline.hpp b/src/hotspot/os/solaris/os_solaris.inline.hpp index 22084022b0f..bdf50f5e039 100644 --- a/src/hotspot/os/solaris/os_solaris.inline.hpp +++ b/src/hotspot/os/solaris/os_solaris.inline.hpp @@ -92,10 +92,6 @@ inline int os::socket(int domain, int type, int protocol) { return ::socket(domain, type, protocol); } -inline struct hostent* os::get_host_by_name(char* name) { - return ::gethostbyname(name); -} - inline bool os::supports_monotonic_clock() { // javaTimeNanos() is monotonic on Solaris, see getTimeNanos() comments return true; diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index 3bf386634a3..c9c18fa7b99 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -5615,10 +5615,6 @@ static jint initSock() { return JNI_OK; } -struct hostent* os::get_host_by_name(char* name) { - return (struct hostent*)gethostbyname(name); -} - int os::socket_close(int fd) { return ::closesocket(fd); } diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index 7aaa2337248..245258c4f4d 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -1395,7 +1395,9 @@ void CodeCache::report_codemem_full(int code_blob_type, bool print) { CodeHeap* heap = get_code_heap(code_blob_type); assert(heap != NULL, "heap is null"); - if ((heap->full_count() == 0) || print) { + heap->report_full(); + + if ((heap->full_count() == 1) || print) { // Not yet reported for this heap, report if (SegmentedCodeCache) { ResourceMark rm; @@ -1432,7 +1434,7 @@ void CodeCache::report_codemem_full(int code_blob_type, bool print) { tty->print("%s", s.as_string()); } - if (heap->full_count() == 0) { + if (heap->full_count() == 1) { LogTarget(Debug, codecache) lt; if (lt.is_enabled()) { CompileBroker::print_heapinfo(tty, "all", 4096); // details, may be a lot! @@ -1440,8 +1442,6 @@ void CodeCache::report_codemem_full(int code_blob_type, bool print) { } } - heap->report_full(); - EventCodeCacheFull event; if (event.should_commit()) { event.set_codeBlobType((u1)code_blob_type); diff --git a/src/hotspot/share/oops/cpCache.cpp b/src/hotspot/share/oops/cpCache.cpp index 9a7ff3a9306..42d35b4c812 100644 --- a/src/hotspot/share/oops/cpCache.cpp +++ b/src/hotspot/share/oops/cpCache.cpp @@ -562,15 +562,14 @@ oop ConstantPoolCacheEntry::method_type_if_resolved(const constantPoolHandle& cp #if INCLUDE_JVMTI void log_adjust(const char* entry_type, Method* old_method, Method* new_method, bool* trace_name_printed) { - if (log_is_enabled(Info, redefine, class, update)) { - ResourceMark rm; - if (!(*trace_name_printed)) { - log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); - *trace_name_printed = true; - } - log_debug(redefine, class, update, constantpool) - ("cpc %s entry update: %s(%s)", entry_type, new_method->name()->as_C_string(), new_method->signature()->as_C_string()); + ResourceMark rm; + + if (!(*trace_name_printed)) { + log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); + *trace_name_printed = true; } + log_trace(redefine, class, update, constantpool) + ("cpc %s entry update: %s", entry_type, new_method->external_name()); } // RedefineClasses() API support: @@ -606,7 +605,7 @@ void ConstantPoolCacheEntry::adjust_method_entry(Method* old_method, // a constant pool cache entry should never contain old or obsolete methods bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() { - Method* m = get_interesting_method_entry(NULL); + Method* m = get_interesting_method_entry(); // return false if m refers to a non-deleted old or obsolete method if (m != NULL) { assert(m->is_valid() && m->is_method(), "m is a valid method"); @@ -616,7 +615,7 @@ bool ConstantPoolCacheEntry::check_no_old_or_obsolete_entries() { } } -Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) { +Method* ConstantPoolCacheEntry::get_interesting_method_entry() { if (!is_method_entry()) { // not a method entry so not interesting by default return NULL; @@ -637,12 +636,9 @@ Method* ConstantPoolCacheEntry::get_interesting_method_entry(Klass* k) { } } assert(m != NULL && m->is_method(), "sanity check"); - if (m == NULL || !m->is_method() || (k != NULL && m->method_holder() != k)) { - // robustness for above sanity checks or method is not in - // the interesting class + if (m == NULL || !m->is_method()) { return NULL; } - // the method is in the interesting class so the entry is interesting return m; } #endif // INCLUDE_JVMTI @@ -801,10 +797,10 @@ void ConstantPoolCache::set_archived_references(oop o) { // RedefineClasses() API support: // If any entry of this ConstantPoolCache points to any of // old_methods, replace it with the corresponding new_method. -void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) { +void ConstantPoolCache::adjust_method_entries(bool * trace_name_printed) { for (int i = 0; i < length(); i++) { ConstantPoolCacheEntry* entry = entry_at(i); - Method* old_method = entry->get_interesting_method_entry(holder); + Method* old_method = entry->get_interesting_method_entry(); if (old_method == NULL || !old_method->is_old()) { continue; // skip uninteresting entries } @@ -813,20 +809,20 @@ void ConstantPoolCache::adjust_method_entries(InstanceKlass* holder, bool * trac entry->initialize_entry(entry->constant_pool_index()); continue; } - Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum()); - - assert(new_method != NULL, "method_with_idnum() should not be NULL"); - assert(old_method != new_method, "sanity check"); - + Method* new_method = old_method->get_new_method(); entry_at(i)->adjust_method_entry(old_method, new_method, trace_name_printed); } } // the constant pool cache should never contain old or obsolete methods bool ConstantPoolCache::check_no_old_or_obsolete_entries() { + ResourceMark rm; for (int i = 1; i < length(); i++) { - if (entry_at(i)->get_interesting_method_entry(NULL) != NULL && - !entry_at(i)->check_no_old_or_obsolete_entries()) { + Method* m = entry_at(i)->get_interesting_method_entry(); + if (m != NULL && !entry_at(i)->check_no_old_or_obsolete_entries()) { + log_trace(redefine, class, update, constantpool) + ("cpcache check found old method entry: class: %s, old: %d, obsolete: %d, method: %s", + constant_pool()->pool_holder()->external_name(), m->is_old(), m->is_obsolete(), m->external_name()); return false; } } @@ -835,7 +831,7 @@ bool ConstantPoolCache::check_no_old_or_obsolete_entries() { void ConstantPoolCache::dump_cache() { for (int i = 1; i < length(); i++) { - if (entry_at(i)->get_interesting_method_entry(NULL) != NULL) { + if (entry_at(i)->get_interesting_method_entry() != NULL) { entry_at(i)->print(tty, i); } } diff --git a/src/hotspot/share/oops/cpCache.hpp b/src/hotspot/share/oops/cpCache.hpp index 2a93500b794..f41ce35541c 100644 --- a/src/hotspot/share/oops/cpCache.hpp +++ b/src/hotspot/share/oops/cpCache.hpp @@ -385,7 +385,7 @@ class ConstantPoolCacheEntry { void adjust_method_entry(Method* old_method, Method* new_method, bool* trace_name_printed); bool check_no_old_or_obsolete_entries(); - Method* get_interesting_method_entry(Klass* k); + Method* get_interesting_method_entry(); #endif // INCLUDE_JVMTI // Debugging & Printing @@ -506,7 +506,7 @@ class ConstantPoolCache: public MetaspaceObj { // trace_name_printed is set to true if the current call has // printed the klass name so that other routines in the adjust_* // group don't print the klass name. - void adjust_method_entries(InstanceKlass* holder, bool* trace_name_printed); + void adjust_method_entries(bool* trace_name_printed); bool check_no_old_or_obsolete_entries(); void dump_cache(); #endif // INCLUDE_JVMTI diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 113908c20c8..dd8eaf3ed95 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -3009,22 +3009,18 @@ int InstanceKlass::vtable_index_of_interface_method(Method* intf_method) { // not yet in the vtable due to concurrent subclass define and superinterface // redefinition // Note: those in the vtable, should have been updated via adjust_method_entries -void InstanceKlass::adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed) { +void InstanceKlass::adjust_default_methods(bool* trace_name_printed) { // search the default_methods for uses of either obsolete or EMCP methods if (default_methods() != NULL) { for (int index = 0; index < default_methods()->length(); index ++) { Method* old_method = default_methods()->at(index); - if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) { + if (old_method == NULL || !old_method->is_old()) { continue; // skip uninteresting entries } assert(!old_method->is_deleted(), "default methods may not be deleted"); - - Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum()); - - assert(new_method != NULL, "method_with_idnum() should not be NULL"); - assert(old_method != new_method, "sanity check"); - + Method* new_method = old_method->get_new_method(); default_methods()->at_put(index, new_method); + if (log_is_enabled(Info, redefine, class, update)) { ResourceMark rm; if (!(*trace_name_printed)) { diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 98736a770dd..15d6ccf6678 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -1171,7 +1171,7 @@ class InstanceKlass: public Klass { int vtable_index_of_interface_method(Method* method); #if INCLUDE_JVMTI - void adjust_default_methods(InstanceKlass* holder, bool* trace_name_printed); + void adjust_default_methods(bool* trace_name_printed); #endif // INCLUDE_JVMTI void clean_weak_instanceklass_links(); diff --git a/src/hotspot/share/oops/klassVtable.cpp b/src/hotspot/share/oops/klassVtable.cpp index 9d4a8ca6346..7637a07f3d5 100644 --- a/src/hotspot/share/oops/klassVtable.cpp +++ b/src/hotspot/share/oops/klassVtable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -964,21 +964,20 @@ bool klassVtable::adjust_default_method(int vtable_index, Method* old_method, Me } // search the vtable for uses of either obsolete or EMCP methods -void klassVtable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) { +void klassVtable::adjust_method_entries(bool * trace_name_printed) { int prn_enabled = 0; + ResourceMark rm; + for (int index = 0; index < length(); index++) { Method* old_method = unchecked_method_at(index); - if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) { + if (old_method == NULL || !old_method->is_old()) { continue; // skip uninteresting entries } assert(!old_method->is_deleted(), "vtable methods may not be deleted"); - Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum()); - - assert(new_method != NULL, "method_with_idnum() should not be NULL"); - assert(old_method != new_method, "sanity check"); - + Method* new_method = old_method->get_new_method(); put_method_at(new_method, index); + // For default methods, need to update the _default_methods array // which can only have one method entry for a given signature bool updated_default = false; @@ -986,27 +985,29 @@ void klassVtable::adjust_method_entries(InstanceKlass* holder, bool * trace_name updated_default = adjust_default_method(index, old_method, new_method); } - if (log_is_enabled(Info, redefine, class, update)) { - ResourceMark rm; - if (!(*trace_name_printed)) { - log_info(redefine, class, update) - ("adjust: klassname=%s for methods from name=%s", - _klass->external_name(), old_method->method_holder()->external_name()); - *trace_name_printed = true; - } - log_debug(redefine, class, update, vtables) - ("vtable method update: %s(%s), updated default = %s", - new_method->name()->as_C_string(), new_method->signature()->as_C_string(), updated_default ? "true" : "false"); + if (!(*trace_name_printed)) { + log_info(redefine, class, update) + ("adjust: klassname=%s for methods from name=%s", + _klass->external_name(), old_method->method_holder()->external_name()); + *trace_name_printed = true; } + log_trace(redefine, class, update, vtables) + ("vtable method update: class: %s method: %s, updated default = %s", + _klass->external_name(), new_method->external_name(), updated_default ? "true" : "false"); } } // a vtable should never contain old or obsolete methods bool klassVtable::check_no_old_or_obsolete_entries() { + ResourceMark rm; + for (int i = 0; i < length(); i++) { Method* m = unchecked_method_at(i); if (m != NULL && (NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) { + log_trace(redefine, class, update, vtables) + ("vtable check found old method entry: class: %s old: %d obsolete: %d, method: %s", + _klass->external_name(), m->is_old(), m->is_obsolete(), m->external_name()); return false; } } @@ -1294,42 +1295,40 @@ void klassItable::initialize_itable_for_interface(int method_table_offset, Klass #if INCLUDE_JVMTI // search the itable for uses of either obsolete or EMCP methods -void klassItable::adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed) { - +void klassItable::adjust_method_entries(bool * trace_name_printed) { + ResourceMark rm; itableMethodEntry* ime = method_entry(0); + for (int i = 0; i < _size_method_table; i++, ime++) { Method* old_method = ime->method(); - if (old_method == NULL || old_method->method_holder() != holder || !old_method->is_old()) { + if (old_method == NULL || !old_method->is_old()) { continue; // skip uninteresting entries } assert(!old_method->is_deleted(), "itable methods may not be deleted"); - - Method* new_method = holder->method_with_idnum(old_method->orig_method_idnum()); - - assert(new_method != NULL, "method_with_idnum() should not be NULL"); - assert(old_method != new_method, "sanity check"); - + Method* new_method = old_method->get_new_method(); ime->initialize(new_method); - if (log_is_enabled(Info, redefine, class, update)) { - ResourceMark rm; - if (!(*trace_name_printed)) { - log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); - *trace_name_printed = true; - } - log_trace(redefine, class, update, itables) - ("itable method update: %s(%s)", new_method->name()->as_C_string(), new_method->signature()->as_C_string()); + if (!(*trace_name_printed)) { + log_info(redefine, class, update)("adjust: name=%s", old_method->method_holder()->external_name()); + *trace_name_printed = true; } + log_trace(redefine, class, update, itables) + ("itable method update: class: %s method: %s", _klass->external_name(), new_method->external_name()); } } // an itable should never contain old or obsolete methods bool klassItable::check_no_old_or_obsolete_entries() { + ResourceMark rm; itableMethodEntry* ime = method_entry(0); + for (int i = 0; i < _size_method_table; i++) { Method* m = ime->method(); if (m != NULL && (NOT_PRODUCT(!m->is_valid() ||) m->is_old() || m->is_obsolete())) { + log_trace(redefine, class, update, itables) + ("itable check found old method entry: class: %s old: %d obsolete: %d, method: %s", + _klass->external_name(), m->is_old(), m->is_obsolete(), m->external_name()); return false; } ime++; diff --git a/src/hotspot/share/oops/klassVtable.hpp b/src/hotspot/share/oops/klassVtable.hpp index c69aeab550b..9cd5e1b3e33 100644 --- a/src/hotspot/share/oops/klassVtable.hpp +++ b/src/hotspot/share/oops/klassVtable.hpp @@ -103,7 +103,7 @@ class klassVtable { // printed the klass name so that other routines in the adjust_* // group don't print the klass name. bool adjust_default_method(int vtable_index, Method* old_method, Method* new_method); - void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed); + void adjust_method_entries(bool* trace_name_printed); bool check_no_old_or_obsolete_entries(); void dump_vtable(); #endif // INCLUDE_JVMTI @@ -322,7 +322,7 @@ class klassItable { // trace_name_printed is set to true if the current call has // printed the klass name so that other routines in the adjust_* // group don't print the klass name. - void adjust_method_entries(InstanceKlass* holder, bool * trace_name_printed); + void adjust_method_entries(bool* trace_name_printed); bool check_no_old_or_obsolete_entries(); void dump_itable(); #endif // INCLUDE_JVMTI diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 0a22263d359..67711d287f9 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -1320,7 +1320,7 @@ Node *LoopLimitNode::Ideal(PhaseGVN *phase, bool can_reshape) { const TypeInt* init_t = phase->type(in(Init) )->is_int(); const TypeInt* limit_t = phase->type(in(Limit))->is_int(); - int stride_p; + jlong stride_p; jlong lim, ini; julong max; if (stride_con > 0) { @@ -1329,10 +1329,10 @@ Node *LoopLimitNode::Ideal(PhaseGVN *phase, bool can_reshape) { ini = init_t->_lo; max = (julong)max_jint; } else { - stride_p = -stride_con; + stride_p = -(jlong)stride_con; lim = init_t->_hi; ini = limit_t->_lo; - max = (julong)min_jint; + max = (julong)(juint)min_jint; // double cast to get 0x0000000080000000, not 0xffffffff80000000 } julong range = lim - ini + stride_p; if (range <= max) { diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 6a9cc8755f5..2652a7a6d5b 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -3559,6 +3559,10 @@ int SWPointer::Tracer::_depth = 0; SWPointer::SWPointer(MemNode* mem, SuperWord* slp, Node_Stack *nstack, bool analyze_only) : _mem(mem), _slp(slp), _base(NULL), _adr(NULL), _scale(0), _offset(0), _invar(NULL), _negate_invar(false), + _has_int_index_after_convI2L(false), + _int_index_after_convI2L_offset(0), + _int_index_after_convI2L_invar(NULL), + _int_index_after_convI2L_scale(0), _nstack(nstack), _analyze_only(analyze_only), _stack_idx(0) #ifndef PRODUCT @@ -3617,6 +3621,11 @@ SWPointer::SWPointer(MemNode* mem, SuperWord* slp, Node_Stack *nstack, bool anal NOT_PRODUCT(if(_slp->is_trace_alignment()) _tracer.restore_depth();) NOT_PRODUCT(_tracer.ctor_6(mem);) + if (!is_safe_to_use_as_simple_form(base, adr)) { + assert(!valid(), "does not have simple form"); + return; + } + _base = base; _adr = adr; assert(valid(), "Usable"); @@ -3627,6 +3636,10 @@ SWPointer::SWPointer(MemNode* mem, SuperWord* slp, Node_Stack *nstack, bool anal SWPointer::SWPointer(SWPointer* p) : _mem(p->_mem), _slp(p->_slp), _base(NULL), _adr(NULL), _scale(0), _offset(0), _invar(NULL), _negate_invar(false), + _has_int_index_after_convI2L(false), + _int_index_after_convI2L_offset(0), + _int_index_after_convI2L_invar(NULL), + _int_index_after_convI2L_scale(0), _nstack(p->_nstack), _analyze_only(p->_analyze_only), _stack_idx(p->_stack_idx) #ifndef PRODUCT @@ -3634,6 +3647,354 @@ SWPointer::SWPointer(SWPointer* p) : #endif {} +// We would like to make decisions about aliasing (i.e. removing memory edges) and adjacency +// (i.e. which loads/stores can be packed) based on the simple form: +// +// s_pointer = adr + offset + invar + scale * ConvI2L(iv) +// +// However, we parse the compound-long-int form: +// +// c_pointer = adr + long_offset + long_invar + long_scale * ConvI2L(int_index) +// int_index = int_offset + int_invar + int_scale * iv +// +// In general, the simple and the compound-long-int form do not always compute the same pointer +// at runtime. For example, the simple form would give a different result due to an overflow +// in the int_index. +// +// Example: +// For both forms, we have: +// iv = 0 +// scale = 1 +// +// We now account the offset and invar once to the long part and once to the int part: +// Pointer 1 (long offset and long invar): +// long_offset = min_int +// long_invar = min_int +// int_offset = 0 +// int_invar = 0 +// +// Pointer 2 (int offset and int invar): +// long_offset = 0 +// long_invar = 0 +// int_offset = min_int +// int_invar = min_int +// +// This gives us the following pointers: +// Compound-long-int form pointers: +// Form: +// c_pointer = adr + long_offset + long_invar + long_scale * ConvI2L(int_offset + int_invar + int_scale * iv) +// +// Pointers: +// c_pointer1 = adr + min_int + min_int + 1 * ConvI2L(0 + 0 + 1 * 0) +// = adr + min_int + min_int +// = adr - 2^32 +// +// c_pointer2 = adr + 0 + 0 + 1 * ConvI2L(min_int + min_int + 1 * 0) +// = adr + ConvI2L(min_int + min_int) +// = adr + 0 +// = adr +// +// Simple form pointers: +// Form: +// s_pointer = adr + offset + invar + scale * ConvI2L(iv) +// s_pointer = adr + (long_offset + int_offset) + (long_invar + int_invar) + (long_scale * int_scale) * ConvI2L(iv) +// +// Pointers: +// s_pointer1 = adr + (min_int + 0 ) + (min_int + 0 ) + 1 * 0 +// = adr + min_int + min_int +// = adr - 2^32 +// s_pointer2 = adr + (0 + min_int ) + (0 + min_int ) + 1 * 0 +// = adr + min_int + min_int +// = adr - 2^32 +// +// We see that the two addresses are actually 2^32 bytes apart (derived from the c_pointers), but their simple form look identical. +// +// Hence, we need to determine in which cases it is safe to make decisions based on the simple +// form, rather than the compound-long-int form. If we cannot prove that using the simple form +// is safe (i.e. equivalent to the compound-long-int form), then we do not get a valid SWPointer, +// and the associated memop cannot be vectorized. +bool SWPointer::is_safe_to_use_as_simple_form(Node* base, Node* adr) const { +#ifndef _LP64 + // On 32-bit platforms, there is never an explicit int_index with ConvI2L for the iv. Thus, the + // parsed pointer form is always the simple form, with int operations: + // + // pointer = adr + offset + invar + scale * iv + // + assert(!_has_int_index_after_convI2L, "32-bit never has an int_index with ConvI2L for the iv"); + return true; +#else + + // Array accesses that are not Unsafe always have a RangeCheck which ensures that there is no + // int_index overflow. This implies that the conversion to long can be done separately: + // + // ConvI2L(int_index) = ConvI2L(int_offset) + ConvI2L(int_invar) + ConvI2L(scale) * ConvI2L(iv) + // + // And hence, the simple form is guaranteed to be identical to the compound-long-int form at + // runtime and the SWPointer is safe/valid to be used. + const TypeAryPtr* ary_ptr_t = _mem->adr_type()->isa_aryptr(); + if (ary_ptr_t != NULL) { + if (!_mem->is_unsafe_access()) { + return true; + } + } + + // We did not find the int_index. Just to be safe, reject this SWPointer. + if (!_has_int_index_after_convI2L) { + return false; + } + + int int_offset = _int_index_after_convI2L_offset; + Node* int_invar = _int_index_after_convI2L_invar; + int int_scale = _int_index_after_convI2L_scale; + int long_scale = _scale / int_scale; + + // If "int_index = iv", then the simple form is identical to the compound-long-int form. + // + // int_index = int_offset + int_invar + int_scale * iv + // = 0 0 1 * iv + // = iv + if (int_offset == 0 && int_invar == NULL && int_scale == 1) { + return true; + } + + // Intuition: What happens if the int_index overflows? Let us look at two pointers on the "overflow edge": + // + // pointer1 = adr + ConvI2L(int_index1) + // pointer2 = adr + ConvI2L(int_index2) + // + // int_index1 = max_int + 0 = max_int -> very close to but before the overflow + // int_index2 = max_int + 1 = min_int -> just enough to get the overflow + // + // When looking at the difference of pointer1 and pointer2, we notice that it is very large + // (almost 2^32). Since arrays have at most 2^31 elements, chances are high that pointer2 is + // an actual out-of-bounds access at runtime. These would normally be prevented by range checks + // at runtime. However, if the access was done by using Unsafe, where range checks are omitted, + // then an out-of-bounds access constitutes undefined behavior. This means that we are allowed to + // do anything, including changing the behavior. + // + // If we can set the right conditions, we have a guarantee that an overflow is either impossible + // (no overflow or range checks preventing that) or undefined behavior. In both cases, we are + // safe to do a vectorization. + // + // Approach: We want to prove a lower bound for the distance between these two pointers, and an + // upper bound for the size of a memory object. We can derive such an upper bound for + // arrays. We know they have at most 2^31 elements. If we know the size of the elements + // in bytes, we have: + // + // array_element_size_in_bytes * 2^31 >= max_possible_array_size_in_bytes + // >= array_size_in_bytes (ARR) + // + // If some small difference "delta" leads to an int_index overflow, we know that the + // int_index1 before overflow must have been close to max_int, and the int_index2 after + // the overflow must be close to min_int: + // + // pointer1 = adr + long_offset + long_invar + long_scale * ConvI2L(int_index1) + // =approx adr + long_offset + long_invar + long_scale * max_int + // + // pointer2 = adr + long_offset + long_invar + long_scale * ConvI2L(int_index2) + // =approx adr + long_offset + long_invar + long_scale * min_int + // + // We realize that the pointer difference is very large: + // + // difference =approx long_scale * 2^32 + // + // Hence, if we set the right condition for long_scale and array_element_size_in_bytes, + // we can prove that an overflow is impossible (or would imply undefined behaviour). + // + // We must now take this intuition, and develop a rigorous proof. We start by stating the problem + // more precisely, with the help of some definitions and the Statement we are going to prove. + // + // Definition: + // Two SWPointers are "comparable" (i.e. SWPointer::comparable is true, set with SWPointer::cmp()), + // iff all of these conditions apply for the simple form: + // 1) Both SWPointers are valid. + // 2) The adr are identical, or both are array bases of different arrays. + // 3) They have identical scale. + // 4) They have identical invar. + // 5) The difference in offsets is limited: abs(offset1 - offset2) < 2^31. (DIFF) + // + // For the Vectorization Optimization, we pair-wise compare SWPointers and determine if they are: + // 1) "not comparable": + // We do not optimize them (assume they alias, not assume adjacency). + // + // Whenever we chose this option based on the simple form, it is also correct based on the + // compound-long-int form, since we make no optimizations based on it. + // + // 2) "comparable" with different array bases at runtime: + // We assume they do not alias (remove memory edges), but not assume adjacency. + // + // Whenever we have two different array bases for the simple form, we also have different + // array bases for the compound-long-form. Since SWPointers provably point to different + // memory objects, they can never alias. + // + // 3) "comparable" with the same base address: + // We compute the relative pointer difference, and based on the load/store size we can + // compute aliasing and adjacency. + // + // We must find a condition under which the pointer difference of the simple form is + // identical to the pointer difference of the compound-long-form. We do this with the + // Statement below, which we then proceed to prove. + // + // Statement: + // If two SWPointers satisfy these 3 conditions: + // 1) They are "comparable". + // 2) They have the same base address. + // 3) Their long_scale is a multiple of the array element size in bytes: + // + // abs(long_scale) % array_element_size_in_bytes = 0 (A) + // + // Then their pointer difference of the simple form is identical to the pointer difference + // of the compound-long-int form. + // + // More precisely: + // Such two SWPointers by definition have identical adr, invar, and scale. + // Their simple form is: + // + // s_pointer1 = adr + offset1 + invar + scale * ConvI2L(iv) (B1) + // s_pointer2 = adr + offset2 + invar + scale * ConvI2L(iv) (B2) + // + // Thus, the pointer difference of the simple forms collapses to the difference in offsets: + // + // s_difference = s_pointer1 - s_pointer2 = offset1 - offset2 (C) + // + // Their compound-long-int form for these SWPointer is: + // + // c_pointer1 = adr + long_offset1 + long_invar1 + long_scale1 * ConvI2L(int_index1) (D1) + // int_index1 = int_offset1 + int_invar1 + int_scale1 * iv (D2) + // + // c_pointer2 = adr + long_offset2 + long_invar2 + long_scale2 * ConvI2L(int_index2) (D3) + // int_index2 = int_offset2 + int_invar2 + int_scale2 * iv (D4) + // + // And these are the offset1, offset2, invar and scale from the simple form (B1) and (B2): + // + // offset1 = long_offset1 + long_scale1 * ConvI2L(int_offset1) (D5) + // offset2 = long_offset2 + long_scale2 * ConvI2L(int_offset2) (D6) + // + // invar = long_invar1 + long_scale1 * ConvI2L(int_invar1) + // = long_invar2 + long_scale2 * ConvI2L(int_invar2) (D7) + // + // scale = long_scale1 * ConvI2L(int_scale1) + // = long_scale2 * ConvI2L(int_scale2) (D8) + // + // The pointer difference of the compound-long-int form is defined as: + // + // c_difference = c_pointer1 - c_pointer2 + // + // Thus, the statement claims that for the two SWPointer we have: + // + // s_difference = c_difference (Statement) + // + // We prove the Statement with the help of a Lemma: + // + // Lemma: + // There is some integer x, such that: + // + // c_difference = s_difference + array_element_size_in_bytes * x * 2^32 (Lemma) + // + // From condition (DIFF), we can derive: + // + // abs(s_difference) < 2^31 (E) + // + // Assuming the Lemma, we prove the Statement: + // If "x = 0" (intuitively: the int_index does not overflow), then: + // c_difference = s_difference + // and hence the simple form computes the same pointer difference as the compound-long-int form. + // If "x != 0" (intuitively: the int_index overflows), then: + // abs(c_difference) >= abs(s_difference + array_element_size_in_bytes * x * 2^32) + // >= array_element_size_in_bytes * 2^32 - abs(s_difference) + // -- apply (E) -- + // > array_element_size_in_bytes * 2^32 - 2^31 + // >= array_element_size_in_bytes * 2^31 + // -- apply (ARR) -- + // >= max_possible_array_size_in_bytes + // >= array_size_in_bytes + // + // This shows that c_pointer1 and c_pointer2 have a distance that exceeds the maximum array size. + // Thus, at least one of the two pointers must be outside of the array bounds. But we can assume + // that out-of-bounds accesses do not happen. If they still do, it is undefined behavior. Hence, + // we are allowed to do anything. We can also "safely" use the simple form in this case even though + // it might not match the compound-long-int form at runtime. + // QED Statement. + // + // We must now prove the Lemma. + // + // ConvI2L always truncates by some power of 2^32, i.e. there is some integer y such that: + // + // ConvI2L(y1 + y2) = ConvI2L(y1) + ConvI2L(y2) + 2^32 * y (F) + // + // It follows, that there is an integer y1 such that: + // + // ConvI2L(int_index1) = ConvI2L(int_offset1 + int_invar1 + int_scale1 * iv) + // -- apply (F) -- + // = ConvI2L(int_offset1) + // + ConvI2L(int_invar1) + // + ConvI2L(int_scale1) * ConvI2L(iv) + // + y1 * 2^32 (G) + // + // Thus, we can write the compound-long-int form (D1) as: + // + // c_pointer1 = adr + long_offset1 + long_invar1 + long_scale1 * ConvI2L(int_index1) + // -- apply (G) -- + // = adr + // + long_offset1 + // + long_invar1 + // + long_scale1 * ConvI2L(int_offset1) + // + long_scale1 * ConvI2L(int_invar1) + // + long_scale1 * ConvI2L(int_scale1) * ConvI2L(iv) + // + long_scale1 * y1 * 2^32 (H) + // + // And we can write the simple form as: + // + // s_pointer1 = adr + offset1 + invar + scale * ConvI2L(iv) + // -- apply (D5, D7, D8) -- + // = adr + // + long_offset1 + // + long_scale1 * ConvI2L(int_offset1) + // + long_invar1 + // + long_scale1 * ConvI2L(int_invar1) + // + long_scale1 * ConvI2L(int_scale1) * ConvI2L(iv) (K) + // + // We now compute the pointer difference between the simple (K) and compound-long-int form (H). + // Most terms cancel out immediately: + // + // sc_difference1 = c_pointer1 - s_pointer1 = long_scale1 * y1 * 2^32 (L) + // + // Rearranging the equation (L), we get: + // + // c_pointer1 = s_pointer1 + long_scale1 * y1 * 2^32 (M) + // + // And since long_scale1 is a multiple of array_element_size_in_bytes, there is some integer + // x1, such that (M) implies: + // + // c_pointer1 = s_pointer1 + array_element_size_in_bytes * x1 * 2^32 (N) + // + // With an analogue equation for c_pointer2, we can now compute the pointer difference for + // the compound-long-int form: + // + // c_difference = c_pointer1 - c_pointer2 + // -- apply (N) -- + // = s_pointer1 + array_element_size_in_bytes * x1 * 2^32 + // -(s_pointer2 + array_element_size_in_bytes * x2 * 2^32) + // -- where "x = x1 - x2" -- + // = s_pointer1 - s_pointer2 + array_element_size_in_bytes * x * 2^32 + // -- apply (C) -- + // = s_difference + array_element_size_in_bytes * x * 2^32 + // QED Lemma. + if (ary_ptr_t != NULL) { + BasicType array_element_bt = ary_ptr_t->elem()->array_element_basic_type(); + if (is_java_primitive(array_element_bt)) { + int array_element_size_in_bytes = type2aelembytes(array_element_bt); + if (abs(long_scale) % array_element_size_in_bytes == 0) { + return true; + } + } + } + + // General case: we do not know if it is safe to use the simple form. + return false; +#endif +} + bool SWPointer::is_main_loop_member(Node* n) const { Node* n_c = phase()->get_ctrl(n); return lpt()->is_member(phase()->get_loop(n_c)); @@ -3683,11 +4044,41 @@ bool SWPointer::scaled_iv_plus_offset(Node* n) { } } else if (opc == Op_SubI) { if (offset_plus_k(n->in(2), true) && scaled_iv_plus_offset(n->in(1))) { + // (offset1 + invar1 + scale * iv) - (offset2) or + // (offset1 + scale * iv) - (offset2 + invar1) + // Subtraction handled via "negate" flag of "offset_plus_k". NOT_PRODUCT(_tracer.scaled_iv_plus_offset_6(n);) return true; } - if (offset_plus_k(n->in(1)) && scaled_iv_plus_offset(n->in(2))) { - _scale *= -1; + SWPointer tmp(this); + if (offset_plus_k(n->in(1)) && tmp.scaled_iv_plus_offset(n->in(2))) { + // (offset1 + invar1) - (offset2 + scale * iv) or + // (offset1) - (offset2 + invar1 + scale * iv) + // Subtraction handled explicitly below. + assert(_scale == 0, "shouldn't be set yet"); + // _scale = -tmp._scale + if (!try_MulI_no_overflow(-1, tmp._scale, _scale)) { + return false; // mul overflow. + } + // _offset -= tmp._offset + if (!try_SubI_no_overflow(_offset, tmp._offset, _offset)) { + return false; // sub overflow. + } + // _invar -= tmp._invar + if (tmp._invar != NULL) { + if (_invar != NULL) { + return false; + } + _invar = tmp._invar; + _negate_invar = !tmp._negate_invar; + } + + // SWPointer tmp does not have an integer part to be forwarded + // (tmp._has_int_index_after_convI2L is false) because n is a SubI, all + // nodes above must also be of integer type (ConvL2I is not handled + // to allow a long) and ConvI2L (the only node that can add an integer + // part) won't be present. + NOT_PRODUCT(_tracer.scaled_iv_plus_offset_7(n);) return true; } @@ -3730,17 +4121,59 @@ bool SWPointer::scaled_iv(Node* n) { } } else if (opc == Op_LShiftI) { if (n->in(1) == iv() && n->in(2)->is_Con()) { - _scale = 1 << n->in(2)->get_int(); + if (!try_LShiftI_no_overflow(1, n->in(2)->get_int(), _scale)) { + return false; // shift overflow. + } NOT_PRODUCT(_tracer.scaled_iv_6(n, _scale);) return true; } - } else if (opc == Op_ConvI2L) { + } else if (opc == Op_ConvI2L && !has_iv()) { if (n->in(1)->Opcode() == Op_CastII && n->in(1)->as_CastII()->has_range_check()) { // Skip range check dependent CastII nodes n = n->in(1); } - if (scaled_iv_plus_offset(n->in(1))) { + + // So far we have not found the iv yet, and are about to enter a ConvI2L subgraph, + // which may be the int index (that might overflow) for the memory access, of the form: + // + // int_index = int_offset + int_invar + int_scale * iv + // + // If we simply continue parsing with the current SWPointer, then the int_offset and + // int_invar simply get added to the long offset and invar. But for the checks in + // SWPointer::is_safe_to_use_as_simple_form() we need to have explicit access to the + // int_index. Thus, we must parse it explicitly here. For this, we use a temporary + // SWPointer, to pattern match the int_index sub-expression of the address. + + NOT_PRODUCT(Tracer::Depth dddd;) + SWPointer tmp(this); + NOT_PRODUCT(_tracer.scaled_iv_8(n, &tmp);) + + if (tmp.scaled_iv_plus_offset(n->in(1)) && tmp.has_iv()) { + // We successfully matched an integer index, of the form: + // int_index = int_offset + int_invar + int_scale * iv + // Forward scale. + assert(_scale == 0 && tmp._scale != 0, "iv only found just now"); + _scale = tmp._scale; + // Accumulate offset. + if (!try_AddI_no_overflow(_offset, tmp._offset, _offset)) { + return false; // add overflow. + } + // Forward invariant if not already found. + if (tmp._invar != NULL) { + if (_invar != NULL) { + return false; + } + _invar = tmp._invar; + _negate_invar = tmp._negate_invar; + } + // Set info about the int_index: + assert(!_has_int_index_after_convI2L, "no previous int_index discovered"); + _has_int_index_after_convI2L = true; + _int_index_after_convI2L_offset = tmp._offset; + _int_index_after_convI2L_invar = tmp._invar; + _int_index_after_convI2L_scale = tmp._scale; + NOT_PRODUCT(_tracer.scaled_iv_7(n);) return true; } @@ -3755,11 +4188,30 @@ bool SWPointer::scaled_iv(Node* n) { if (tmp.scaled_iv_plus_offset(n->in(1))) { if (tmp._invar == NULL || _slp->do_vector_loop()) { - int mult = 1 << n->in(2)->get_int(); - _scale = tmp._scale * mult; - _offset += tmp._offset * mult; + int shift = (int)(n->in(2)->get_int()); + // Accumulate scale. + if (!try_LShiftI_no_overflow(tmp._scale, shift, _scale)) { + return false; // shift overflow. + } + // Accumulate offset. + jint shifted_offset = 0; + if (!try_LShiftI_no_overflow(tmp._offset, shift, shifted_offset)) { + return false; // shift overflow. + } + if (!try_AddI_no_overflow(_offset, shifted_offset, _offset)) { + return false; // add overflow. + } + // Accumulate invar. _invar = tmp._invar; - NOT_PRODUCT(_tracer.scaled_iv_9(n, _scale, _offset, mult);) + + // Forward info about the int_index: + assert(!_has_int_index_after_convI2L, "no previous int_index discovered"); + _has_int_index_after_convI2L = tmp._has_int_index_after_convI2L; + _int_index_after_convI2L_offset = tmp._int_index_after_convI2L_offset; + _int_index_after_convI2L_invar = tmp._int_index_after_convI2L_invar; + _int_index_after_convI2L_scale = tmp._int_index_after_convI2L_scale; + + NOT_PRODUCT(_tracer.scaled_iv_9(n, _scale, _offset, 1 << shift);) return true; } } @@ -3778,7 +4230,9 @@ bool SWPointer::offset_plus_k(Node* n, bool negate) { int opc = n->Opcode(); if (opc == Op_ConI) { - _offset += negate ? -(n->get_int()) : n->get_int(); + if (!try_AddSubI_no_overflow(_offset, n->get_int(), negate, _offset)) { + return false; // add/sub overflow. + } NOT_PRODUCT(_tracer.offset_plus_k_2(n, _offset);) return true; } else if (opc == Op_ConL) { @@ -3787,7 +4241,9 @@ bool SWPointer::offset_plus_k(Node* n, bool negate) { if (t->higher_equal(TypeLong::INT)) { jlong loff = n->get_long(); jint off = (jint)loff; - _offset += negate ? -off : loff; + if (!try_AddSubI_no_overflow(_offset, off, negate, _offset)) { + return false; // add/sub overflow. + } NOT_PRODUCT(_tracer.offset_plus_k_3(n, _offset);) return true; } @@ -3806,11 +4262,15 @@ bool SWPointer::offset_plus_k(Node* n, bool negate) { if (n->in(2)->is_Con() && invariant(n->in(1))) { _negate_invar = negate; _invar = n->in(1); - _offset += negate ? -(n->in(2)->get_int()) : n->in(2)->get_int(); + if (!try_AddSubI_no_overflow(_offset, n->in(2)->get_int(), negate, _offset)) { + return false; // add/sub overflow. + } NOT_PRODUCT(_tracer.offset_plus_k_6(n, _invar, _negate_invar, _offset);) return true; } else if (n->in(1)->is_Con() && invariant(n->in(2))) { - _offset += negate ? -(n->in(1)->get_int()) : n->in(1)->get_int(); + if (!try_AddSubI_no_overflow(_offset, n->in(1)->get_int(), negate, _offset)) { + return false; // add/sub overflow. + } _negate_invar = negate; _invar = n->in(2); NOT_PRODUCT(_tracer.offset_plus_k_7(n, _invar, _negate_invar, _offset);) @@ -3821,11 +4281,15 @@ bool SWPointer::offset_plus_k(Node* n, bool negate) { if (n->in(2)->is_Con() && invariant(n->in(1))) { _negate_invar = negate; _invar = n->in(1); - _offset += !negate ? -(n->in(2)->get_int()) : n->in(2)->get_int(); + if (!try_AddSubI_no_overflow(_offset, n->in(2)->get_int(), !negate, _offset)) { + return false; // add/sub overflow. + } NOT_PRODUCT(_tracer.offset_plus_k_8(n, _invar, _negate_invar, _offset);) return true; } else if (n->in(1)->is_Con() && invariant(n->in(2))) { - _offset += negate ? -(n->in(1)->get_int()) : n->in(1)->get_int(); + if (!try_AddSubI_no_overflow(_offset, n->in(1)->get_int(), negate, _offset)) { + return false; // add/sub overflow. + } _negate_invar = !negate; _invar = n->in(2); NOT_PRODUCT(_tracer.offset_plus_k_9(n, _invar, _negate_invar, _offset);) @@ -3857,6 +4321,57 @@ bool SWPointer::offset_plus_k(Node* n, bool negate) { return false; } +bool SWPointer::try_AddI_no_overflow(jint offset1, jint offset2, jint& result) { + jlong long_offset = java_add((jlong)(offset1), (jlong)(offset2)); + jint int_offset = java_add( offset1, offset2); + if (long_offset != int_offset) { + return false; + } + result = int_offset; + return true; +} + +bool SWPointer::try_SubI_no_overflow(jint offset1, jint offset2, jint& result) { + jlong long_offset = java_subtract((jlong)(offset1), (jlong)(offset2)); + jint int_offset = java_subtract( offset1, offset2); + if (long_offset != int_offset) { + return false; + } + result = int_offset; + return true; +} + +bool SWPointer::try_AddSubI_no_overflow(jint offset1, jint offset2, bool is_sub, jint& result) { + if (is_sub) { + return try_SubI_no_overflow(offset1, offset2, result); + } else { + return try_AddI_no_overflow(offset1, offset2, result); + } +} + +bool SWPointer::try_LShiftI_no_overflow(jint offset, int shift, jint& result) { + if (shift < 0 || shift > 31) { + return false; + } + jlong long_offset = java_shift_left((jlong)(offset), (julong)((jlong)(shift))); + jint int_offset = java_shift_left( offset, (juint)((jint)(shift))); + if (long_offset != int_offset) { + return false; + } + result = int_offset; + return true; +} + +bool SWPointer::try_MulI_no_overflow(jint offset1, jint offset2, jint& result) { + jlong long_offset = java_multiply((jlong)(offset1), (jlong)(offset2)); + jint int_offset = java_multiply( offset1, offset2); + if (long_offset != int_offset) { + return false; + } + result = int_offset; + return true; +} + //----------------------------print------------------------ void SWPointer::print() { #ifndef PRODUCT diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index 65ed7088766..c98c4fbda00 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -568,17 +568,63 @@ class SuperWord : public ResourceObj { //------------------------------SWPointer--------------------------- // Information about an address for dependence checking and vector alignment +// +// We parse and represent pointers of the simple form: +// +// pointer = adr + offset + invar + scale * ConvI2L(iv) +// +// Where: +// +// adr: the base address of an array (base = adr) +// OR +// some address to off-heap memory (base = TOP) +// +// offset: a constant offset +// invar: a runtime variable, which is invariant during the loop +// scale: scaling factor +// iv: loop induction variable +// +// But more precisely, we parse the composite-long-int form: +// +// pointer = adr + long_offset + long_invar + long_scale * ConvI2L(int_offset + inv_invar + int_scale * iv) +// +// pointer = adr + long_offset + long_invar + long_scale * ConvI2L(int_index) +// int_index = int_offset + int_invar + int_scale * iv +// +// However, for aliasing and adjacency checks (e.g. SWPointer::cmp()) we always use the simple form to make +// decisions. Hence, we must make sure to only create a "valid" SWPointer if the optimisations based on the +// simple form produce the same result as the compound-long-int form would. Intuitively, this depends on +// if the int_index overflows, but the precise conditions are given in SWPointer::is_safe_to_use_as_simple_form(). +// +// ConvI2L(int_index) = ConvI2L(int_offset + int_invar + int_scale * iv) +// = Convi2L(int_offset) + ConvI2L(int_invar) + ConvI2L(int_scale) * ConvI2L(iv) +// +// scale = long_scale * ConvI2L(int_scale) +// offset = long_offset + long_scale * ConvI2L(int_offset) +// invar = long_invar + long_scale * ConvI2L(int_invar) +// +// pointer = adr + offset + invar + scale * ConvI2L(iv) +// class SWPointer { protected: MemNode* _mem; // My memory reference node SuperWord* _slp; // SuperWord class - Node* _base; // NULL if unsafe nonheap reference - Node* _adr; // address pointer + // Components of the simple form: + Node* _base; // Base address of an array OR NULL if some off-heap memory. + Node* _adr; // Same as _base if an array pointer OR some off-heap memory pointer. jint _scale; // multiplier for iv (in bytes), 0 if no loop iv jint _offset; // constant offset (in bytes) Node* _invar; // invariant offset (in bytes), NULL if none bool _negate_invar; // if true then use: (0 - _invar) + + // The int_index components of the compound-long-int form. Used to decide if it is safe to use the + // simple form rather than the compound-long-int form that was parsed. + bool _has_int_index_after_convI2L; + int _int_index_after_convI2L_offset; + Node* _int_index_after_convI2L_invar; + int _int_index_after_convI2L_scale; + Node_Stack* _nstack; // stack used to record a swpointer trace of variants bool _analyze_only; // Used in loop unrolling only for swpointer trace uint _stack_idx; // Used in loop unrolling only for swpointer trace @@ -597,6 +643,8 @@ class SWPointer { // Match: offset is (k [+/- invariant]) bool offset_plus_k(Node* n, bool negate = false); + bool is_safe_to_use_as_simple_form(Node* base, Node* adr) const; + public: enum CMP { Less = 1, @@ -625,12 +673,45 @@ class SWPointer { Node_Stack* node_stack() { return _nstack; } // Comparable? + // We compute if and how two SWPointers can alias at runtime, i.e. if the two addressed regions of memory can + // ever overlap. There are essentially 3 relevant return states: + // - NotComparable: Synonymous to "unknown aliasing". + // We have no information about how the two SWPointers can alias. They could overlap, refer + // to another location in the same memory object, or point to a completely different object. + // -> Memory edge required. Aliasing unlikely but possible. + // + // - Less / Greater: Synonymous to "never aliasing". + // The two SWPointers may point into the same memory object, but be non-aliasing (i.e. we + // know both address regions inside the same memory object, but these regions are non- + // overlapping), or the SWPointers point to entirely different objects. + // -> No memory edge required. Aliasing impossible. + // + // - Equal: Synonymous to "overlap, or point to different memory objects". + // The two SWPointers either overlap on the same memory object, or point to two different + // memory objects. + // -> Memory edge required. Aliasing likely. + // + // In a future refactoring, we can simplify to two states: + // - NeverAlias: instead of Less / Greater + // - MayAlias: instead of Equal / NotComparable + // + // Two SWPointer are "comparable" (Less / Greater / Equal), iff all of these conditions apply: + // 1) Both are valid, i.e. expressible in the compound-long-int or simple form. + // 2) The adr are identical, or both are array bases of different arrays. + // 3) They have identical scale. + // 4) They have identical invar. + // 5) The difference in offsets is limited: abs(offset0 - offset1) < 2^31. int cmp(SWPointer& q) { if (valid() && q.valid() && (_adr == q._adr || (_base == _adr && q._base == q._adr)) && _scale == q._scale && _invar == q._invar && _negate_invar == q._negate_invar) { + jlong difference = abs(java_subtract((jlong)_offset, (jlong)q._offset)); + jlong max_diff = (jlong)1 << 31; + if (difference >= max_diff) { + return NotComparable; + } bool overlap = q._offset < _offset + memory_size() && _offset < q._offset + q.memory_size(); return overlap ? Equal : (_offset < q._offset ? Less : Greater); @@ -717,6 +798,13 @@ class SWPointer { } _tracer;//TRacer; #endif + + static bool try_AddI_no_overflow(jint offset1, jint offset2, jint& result); + static bool try_SubI_no_overflow(jint offset1, jint offset2, jint& result); + static bool try_AddSubI_no_overflow(jint offset1, jint offset2, bool is_sub, jint& result); + static bool try_LShiftI_no_overflow(jint offset1, int offset2, jint& result); + static bool try_MulI_no_overflow(jint offset1, jint offset2, jint& result); + }; #endif // SHARE_VM_OPTO_SUPERWORD_HPP diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index aee84b1d7c5..2dcd30a295f 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -59,10 +59,12 @@ Method** VM_RedefineClasses::_matching_old_methods = NULL; Method** VM_RedefineClasses::_matching_new_methods = NULL; Method** VM_RedefineClasses::_deleted_methods = NULL; Method** VM_RedefineClasses::_added_methods = NULL; -int VM_RedefineClasses::_matching_methods_length = 0; -int VM_RedefineClasses::_deleted_methods_length = 0; -int VM_RedefineClasses::_added_methods_length = 0; -Klass* VM_RedefineClasses::_the_class = NULL; +int VM_RedefineClasses::_matching_methods_length = 0; +int VM_RedefineClasses::_deleted_methods_length = 0; +int VM_RedefineClasses::_added_methods_length = 0; + +// This flag is global as the constructor does not reset it: +bool VM_RedefineClasses::_has_redefined_Object = false; VM_RedefineClasses::VM_RedefineClasses(jint class_count, @@ -73,6 +75,7 @@ VM_RedefineClasses::VM_RedefineClasses(jint class_count, _class_load_kind = class_load_kind; _any_class_has_resolved_methods = false; _res = JVMTI_ERROR_NONE; + _the_class = NULL; } static inline InstanceKlass* get_ik(jclass def) { @@ -207,11 +210,12 @@ void VM_RedefineClasses::doit() { redefine_single_class(_class_defs[i].klass, _scratch_classes[i], thread); } - // Clean out MethodData pointing to old Method* + // Adjust constantpool caches and vtables for all classes + // that reference methods of the evolved classes. // Have to do this after all classes are redefined and all methods that // are redefined are marked as old. - MethodDataCleaner clean_weak_method_links; - ClassLoaderDataGraph::classes_do(&clean_weak_method_links); + AdjustAndCleanMetadata adjust_and_clean_metadata(thread); + ClassLoaderDataGraph::classes_do(&adjust_and_clean_metadata); // JSR-292 support if (_any_class_has_resolved_methods) { @@ -3423,103 +3427,74 @@ void VM_RedefineClasses::set_new_constant_pool( // Unevolving classes may point to methods of the_class directly // from their constant pool caches, itables, and/or vtables. We // use the ClassLoaderDataGraph::classes_do() facility and this helper -// to fix up these pointers. +// to fix up these pointers. MethodData also points to old methods and +// must be cleaned. // Adjust cpools and vtables closure -void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { +void VM_RedefineClasses::AdjustAndCleanMetadata::do_klass(Klass* k) { // This is a very busy routine. We don't want too much tracing // printed out. bool trace_name_printed = false; - InstanceKlass *the_class = InstanceKlass::cast(_the_class); // If the class being redefined is java.lang.Object, we need to fix all - // array class vtables also - if (k->is_array_klass() && _the_class == SystemDictionary::Object_klass()) { - k->vtable().adjust_method_entries(the_class, &trace_name_printed); + // array class vtables also. The _has_redefined_Object flag is global. + // Once the java.lang.Object has been redefined (by the current or one + // of the previous VM_RedefineClasses operations) we have to always + // adjust method entries for array classes. + if (k->is_array_klass() && _has_redefined_Object) { + k->vtable().adjust_method_entries(&trace_name_printed); } else if (k->is_instance_klass()) { HandleMark hm(_thread); InstanceKlass *ik = InstanceKlass::cast(k); - // HotSpot specific optimization! HotSpot does not currently - // support delegation from the bootstrap class loader to a - // user-defined class loader. This means that if the bootstrap - // class loader is the initiating class loader, then it will also - // be the defining class loader. This also means that classes - // loaded by the bootstrap class loader cannot refer to classes - // loaded by a user-defined class loader. Note: a user-defined - // class loader can delegate to the bootstrap class loader. - // - // If the current class being redefined has a user-defined class - // loader as its defining class loader, then we can skip all - // classes loaded by the bootstrap class loader. - bool is_user_defined = (_the_class->class_loader() != NULL); - if (is_user_defined && ik->class_loader() == NULL) { - return; + // Clean MethodData of this class's methods so they don't refer to + // old methods that are no longer running. + Array* methods = ik->methods(); + int num_methods = methods->length(); + for (int index = 0; index < num_methods; ++index) { + if (methods->at(index)->method_data() != NULL) { + methods->at(index)->method_data()->clean_weak_method_links(); + } } - // Fix the vtable embedded in the_class and subclasses of the_class, - // if one exists. We discard scratch_class and we don't keep an - // InstanceKlass around to hold obsolete methods so we don't have - // any other InstanceKlass embedded vtables to update. The vtable - // holds the Method*s for virtual (but not final) methods. - // Default methods, or concrete methods in interfaces are stored - // in the vtable, so if an interface changes we need to check - // adjust_method_entries() for every InstanceKlass, which will also - // adjust the default method vtable indices. - // We also need to adjust any default method entries that are - // not yet in the vtable, because the vtable setup is in progress. - // This must be done after we adjust the default_methods and - // default_vtable_indices for methods already in the vtable. - // If redefining Unsafe, walk all the vtables looking for entries. - if (ik->vtable_length() > 0 && (_the_class->is_interface() - || _the_class == SystemDictionary::internal_Unsafe_klass() - || ik->is_subtype_of(_the_class))) { - // ik->vtable() creates a wrapper object; rm cleans it up - ResourceMark rm(_thread); - - ik->vtable().adjust_method_entries(the_class, &trace_name_printed); - ik->adjust_default_methods(the_class, &trace_name_printed); + // Adjust all vtables, default methods and itables, to clean out old methods. + ResourceMark rm(_thread); + if (ik->vtable_length() > 0) { + ik->vtable().adjust_method_entries(&trace_name_printed); + ik->adjust_default_methods(&trace_name_printed); } - // If the current class has an itable and we are either redefining an - // interface or if the current class is a subclass of the_class, then - // we potentially have to fix the itable. If we are redefining an - // interface, then we have to call adjust_method_entries() for - // every InstanceKlass that has an itable since there isn't a - // subclass relationship between an interface and an InstanceKlass. - // If redefining Unsafe, walk all the itables looking for entries. - if (ik->itable_length() > 0 && (_the_class->is_interface() - || _the_class == SystemDictionary::internal_Unsafe_klass() - || ik->is_subclass_of(_the_class))) { - ResourceMark rm(_thread); - ik->itable().adjust_method_entries(the_class, &trace_name_printed); + if (ik->itable_length() > 0) { + ik->itable().adjust_method_entries(&trace_name_printed); } // The constant pools in other classes (other_cp) can refer to - // methods in the_class. We have to update method information in + // old methods. We have to update method information in // other_cp's cache. If other_cp has a previous version, then we // have to repeat the process for each previous version. The // constant pool cache holds the Method*s for non-virtual // methods and for virtual, final methods. // - // Special case: if the current class is the_class, then new_cp - // has already been attached to the_class and old_cp has already - // been added as a previous version. The new_cp doesn't have any - // cached references to old methods so it doesn't need to be - // updated. We can simply start with the previous version(s) in - // that case. - constantPoolHandle other_cp; + // Special case: if the current class is being redefined by the current + // VM_RedefineClasses operation, then new_cp has already been attached + // to the_class and old_cp has already been added as a previous version. + // The new_cp doesn't have any cached references to old methods so it + // doesn't need to be updated and we could optimize by skipping it. + // However, the current class can be marked as being redefined by another + // VM_RedefineClasses operation which has already executed its doit_prologue + // and needs cpcache method entries adjusted. For simplicity, the cpcache + // update is done unconditionally. It should result in doing nothing for + // classes being redefined by the current VM_RedefineClasses operation. + // Method entries in the previous version(s) are adjusted as well. ConstantPoolCache* cp_cache; - if (ik != _the_class) { - // this klass' constant pool cache may need adjustment - other_cp = constantPoolHandle(ik->constants()); - cp_cache = other_cp->cache(); - if (cp_cache != NULL) { - cp_cache->adjust_method_entries(the_class, &trace_name_printed); - } + // this klass' constant pool cache may need adjustment + ConstantPool* other_cp = ik->constants(); + cp_cache = other_cp->cache(); + if (cp_cache != NULL) { + cp_cache->adjust_method_entries(&trace_name_printed); } // the previous versions' constant pool caches may need adjustment @@ -3528,23 +3503,7 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) { pv_node = pv_node->previous_versions()) { cp_cache = pv_node->constants()->cache(); if (cp_cache != NULL) { - cp_cache->adjust_method_entries(pv_node, &trace_name_printed); - } - } - } -} - -// Clean method data for this class -void VM_RedefineClasses::MethodDataCleaner::do_klass(Klass* k) { - if (k->is_instance_klass()) { - InstanceKlass *ik = InstanceKlass::cast(k); - // Clean MethodData of this class's methods so they don't refer to - // old methods that are no longer running. - Array* methods = ik->methods(); - int num_methods = methods->length(); - for (int index = 0; index < num_methods; ++index) { - if (methods->at(index)->method_data() != NULL) { - methods->at(index)->method_data()->clean_weak_method_links(); + cp_cache->adjust_method_entries(&trace_name_printed); } } } @@ -3976,6 +3935,9 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, InstanceKlass* the_class = get_ik(the_jclass); + // Set a flag to control and optimize adjusting method entries + _has_redefined_Object |= the_class == SystemDictionary::Object_klass(); + // Remove all breakpoints in methods of this class JvmtiBreakpoints& jvmti_breakpoints = JvmtiCurrentBreakpoints::get_jvmti_breakpoints(); jvmti_breakpoints.clearall_in_class_at_safepoint(the_class); @@ -4200,11 +4162,6 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass, _timer_rsc_phase2.start(); } - // Adjust constantpool caches and vtables for all classes - // that reference methods of the evolved class. - AdjustCpoolCacheAndVtable adjust_cpool_cache_and_vtable(THREAD); - ClassLoaderDataGraph::classes_do(&adjust_cpool_cache_and_vtable); - if (the_class->oop_map_cache() != NULL) { // Flush references to any obsolete methods from the oop map cache // so that obsolete methods are not pinned. diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.hpp b/src/hotspot/share/prims/jvmtiRedefineClasses.hpp index 8c17d901204..3ab0d921df3 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.hpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.hpp @@ -338,20 +338,22 @@ struct JvmtiCachedClassFileData { class VM_RedefineClasses: public VM_Operation { private: // These static fields are needed by ClassLoaderDataGraph::classes_do() - // facility and the AdjustCpoolCacheAndVtable helper: + // facility and the CheckClass and AdjustAndCleanMetadata helpers. static Array* _old_methods; static Array* _new_methods; - static Method** _matching_old_methods; - static Method** _matching_new_methods; - static Method** _deleted_methods; - static Method** _added_methods; + static Method** _matching_old_methods; + static Method** _matching_new_methods; + static Method** _deleted_methods; + static Method** _added_methods; static int _matching_methods_length; static int _deleted_methods_length; static int _added_methods_length; - static Klass* _the_class; + static bool _has_redefined_Object; + static bool _has_null_class_loader; // The instance fields are used to pass information from // doit_prologue() to doit() and doit_epilogue(). + Klass* _the_class; jint _class_count; const jvmtiClassDefinition *_class_defs; // ptr to _class_count defs @@ -512,20 +514,14 @@ class VM_RedefineClasses: public VM_Operation { // Unevolving classes may point to methods of the_class directly // from their constant pool caches, itables, and/or vtables. We // use the ClassLoaderDataGraph::classes_do() facility and this helper - // to fix up these pointers. - class AdjustCpoolCacheAndVtable : public KlassClosure { + // to fix up these pointers and clean MethodData out. + class AdjustAndCleanMetadata : public KlassClosure { Thread* _thread; public: - AdjustCpoolCacheAndVtable(Thread* t) : _thread(t) {} + AdjustAndCleanMetadata(Thread* t) : _thread(t) {} void do_klass(Klass* k); }; - // Clean MethodData out - class MethodDataCleaner : public KlassClosure { - public: - MethodDataCleaner() {} - void do_klass(Klass* k); - }; public: VM_RedefineClasses(jint class_count, const jvmtiClassDefinition *class_defs, diff --git a/src/hotspot/share/prims/resolvedMethodTable.cpp b/src/hotspot/share/prims/resolvedMethodTable.cpp index f68990f3af9..12d61e6bebb 100644 --- a/src/hotspot/share/prims/resolvedMethodTable.cpp +++ b/src/hotspot/share/prims/resolvedMethodTable.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -222,11 +222,7 @@ void ResolvedMethodTable::adjust_method_entries(bool * trace_name_printed) { if (old_method->is_deleted()) { new_method = Universe::throw_no_such_method_error(); } else { - InstanceKlass* holder = old_method->method_holder(); - new_method = holder->method_with_idnum(old_method->orig_method_idnum()); - assert(holder == new_method->method_holder(), "call after swapping redefined guts"); - assert(new_method != NULL, "method_with_idnum() should not be NULL"); - assert(old_method != new_method, "sanity check"); + new_method = old_method->get_new_method(); } java_lang_invoke_ResolvedMethodName::set_vmtarget(mem_name, new_method); diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 7554653e256..d6cf3dce109 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -834,7 +834,6 @@ class os: AllStatic { static int send(int fd, char* buf, size_t nBytes, uint flags); static int raw_send(int fd, char* buf, size_t nBytes, uint flags); static int connect(int fd, struct sockaddr* him, socklen_t len); - static struct hostent* get_host_by_name(char* name); // Support for signals (see JVM_RaiseSignal, JVM_RegisterSignal) static void initialize_jdk_signal_support(TRAPS); diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index f73b44b001e..63bc94eef01 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -791,15 +791,17 @@ class Thread: public ThreadShadow { class ThreadInAsgct { private: Thread* _thread; + bool _saved_in_asgct; public: ThreadInAsgct(Thread* thread) : _thread(thread) { assert(thread != NULL, "invariant"); - assert(!thread->in_asgct(), "invariant"); + // Allow AsyncGetCallTrace to be reentrant - save the previous state. + _saved_in_asgct = thread->in_asgct(); thread->set_in_asgct(true); } ~ThreadInAsgct() { assert(_thread->in_asgct(), "invariant"); - _thread->set_in_asgct(false); + _thread->set_in_asgct(_saved_in_asgct); } }; diff --git a/src/hotspot/share/services/classLoadingService.cpp b/src/hotspot/share/services/classLoadingService.cpp index 9691f9fa766..6271d348c87 100644 --- a/src/hotspot/share/services/classLoadingService.cpp +++ b/src/hotspot/share/services/classLoadingService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -36,6 +36,7 @@ #include "utilities/defaultStream.hpp" #include "logging/log.hpp" #include "logging/logConfiguration.hpp" +#include "logging/logFileStreamOutput.hpp" #ifdef DTRACE_ENABLED @@ -191,6 +192,22 @@ bool ClassLoadingService::set_verbose(bool verbose) { return verbose; } +bool ClassLoadingService::get_verbose() { + for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) { + // set_verbose looks for a non-exact match for class+load, + // so look for all tag sets that match class+load* + if (ts->contains(LogTag::_class) && + ts->contains(LogTag::_load)) { + LogLevelType l = ts->level_for(&StdoutLog); + if (l != LogLevel::Info && l != LogLevel::Debug && l != LogLevel::Trace) { + return false; + } + } + } + + return true; +} + // Caller to this function must own Management_lock void ClassLoadingService::reset_trace_class_unloading() { assert(Management_lock->owned_by_self(), "Must own the Management_lock"); diff --git a/src/hotspot/share/services/classLoadingService.hpp b/src/hotspot/share/services/classLoadingService.hpp index 5786e59ec01..b08cad37f58 100644 --- a/src/hotspot/share/services/classLoadingService.hpp +++ b/src/hotspot/share/services/classLoadingService.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -55,8 +55,8 @@ class ClassLoadingService : public AllStatic { public: static void init(); - static bool get_verbose() { return log_is_enabled(Info, class, load); } static bool set_verbose(bool verbose); + static bool get_verbose() NOT_MANAGEMENT_RETURN_(false); static void reset_trace_class_unloading() NOT_MANAGEMENT_RETURN; static jlong loaded_class_count() { diff --git a/src/hotspot/share/services/memoryService.cpp b/src/hotspot/share/services/memoryService.cpp index 1e65d8a75c3..292cb9d6c1a 100644 --- a/src/hotspot/share/services/memoryService.cpp +++ b/src/hotspot/share/services/memoryService.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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,7 @@ #include "classfile/vmSymbols.hpp" #include "gc/shared/collectedHeap.hpp" #include "logging/logConfiguration.hpp" +#include "logging/logFileStreamOutput.hpp" #include "memory/heap.hpp" #include "memory/memRegion.hpp" #include "memory/resourceArea.hpp" @@ -215,6 +216,21 @@ bool MemoryService::set_verbose(bool verbose) { return verbose; } +bool MemoryService::get_verbose() { + for (LogTagSet* ts = LogTagSet::first(); ts != NULL; ts = ts->next()) { + // set_verbose only sets gc and not gc*, so check for an exact match + const bool is_gc_exact_match = ts->contains(LogTag::_gc) && ts->ntags() == 1; + if (is_gc_exact_match) { + LogLevelType l = ts->level_for(&StdoutLog); + if (l == LogLevel::Info || l == LogLevel::Debug || l == LogLevel::Trace) { + return true; + } + } + } + + return false; +} + Handle MemoryService::create_MemoryUsage_obj(MemoryUsage usage, TRAPS) { InstanceKlass* ik = Management::java_lang_management_MemoryUsage_klass(CHECK_NH); diff --git a/src/hotspot/share/services/memoryService.hpp b/src/hotspot/share/services/memoryService.hpp index 222918df4b2..9487212d71f 100644 --- a/src/hotspot/share/services/memoryService.hpp +++ b/src/hotspot/share/services/memoryService.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, 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 @@ -107,8 +107,8 @@ class MemoryService : public AllStatic { static void oops_do(OopClosure* f); - static bool get_verbose() { return log_is_enabled(Info, gc); } static bool set_verbose(bool verbose); + static bool get_verbose(); // Create an instance of java/lang/management/MemoryUsage static Handle create_MemoryUsage_obj(MemoryUsage usage, TRAPS); diff --git a/src/hotspot/share/utilities/ostream.cpp b/src/hotspot/share/utilities/ostream.cpp index e8ec46c2c13..746f017bfef 100644 --- a/src/hotspot/share/utilities/ostream.cpp +++ b/src/hotspot/share/utilities/ostream.cpp @@ -1078,7 +1078,7 @@ bufferedStream::~bufferedStream() { #include #include #elif defined(_WINDOWS) -#include +#include #endif // Network access @@ -1119,25 +1119,31 @@ void networkStream::close() { } } -bool networkStream::connect(const char *ip, short port) { +// host could be IP address, or a host name +bool networkStream::connect(const char *host, short port) { - struct sockaddr_in server; - server.sin_family = AF_INET; - server.sin_port = htons(port); + char s_port[6]; // 5 digits max plus terminator + int ret = os::snprintf(s_port, sizeof(s_port), "%hu", (unsigned short) port); + assert(ret > 0, "snprintf failed: %d", ret); - server.sin_addr.s_addr = inet_addr(ip); - if (server.sin_addr.s_addr == (uint32_t)-1) { - struct hostent* host = os::get_host_by_name((char*)ip); - if (host != NULL) { - memcpy(&server.sin_addr, host->h_addr_list[0], host->h_length); - } else { - return false; - } - } + struct addrinfo* addr_info = NULL; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; // Allow IPv4 only + hints.ai_socktype = SOCK_STREAM; // TCP only + + // getaddrinfo can resolve both an IP address and a host name + ret = getaddrinfo(host, s_port, &hints, &addr_info); + if (ret != 0) { + warning("networkStream::connect getaddrinfo for host %s and port %s failed: %s", + host, s_port, gai_strerror(ret)); + return false; + } - int result = os::connect(_socket, (struct sockaddr*)&server, sizeof(struct sockaddr_in)); - return (result >= 0); + ret = os::connect(_socket, addr_info->ai_addr, (socklen_t)addr_info->ai_addrlen); + freeaddrinfo(addr_info); + return (ret >= 0); } #endif diff --git a/src/java.base/share/classes/java/lang/StringCoding.java b/src/java.base/share/classes/java/lang/StringCoding.java index 097c1566542..da2be7d28d3 100644 --- a/src/java.base/share/classes/java/lang/StringCoding.java +++ b/src/java.base/share/classes/java/lang/StringCoding.java @@ -772,9 +772,9 @@ private static Result decodeUTF8_0(byte[] src, int sp, int len, boolean doReplac } } if (dp == 0) { - dst = new byte[len << 1]; + dst = StringUTF16.newBytesFor(len); } else { - byte[] buf = new byte[len << 1]; + byte[] buf = StringUTF16.newBytesFor(len); StringLatin1.inflate(dst, 0, buf, 0, dp); dst = buf; } @@ -910,7 +910,7 @@ private static byte[] encodeUTF8(byte coder, byte[] val, boolean doReplace) { return Arrays.copyOf(val, val.length); int dp = 0; - byte[] dst = new byte[val.length << 1]; + byte[] dst = StringUTF16.newBytesFor(val.length); for (int sp = 0; sp < val.length; sp++) { byte c = val[sp]; if (c < 0) { diff --git a/src/java.base/share/classes/java/net/doc-files/net-properties.html b/src/java.base/share/classes/java/net/doc-files/net-properties.html index cef44d1422a..795d99d926b 100644 --- a/src/java.base/share/classes/java/net/doc-files/net-properties.html +++ b/src/java.base/share/classes/java/net/doc-files/net-properties.html @@ -238,6 +238,15 @@

Misc HTTP URL stream protocol handler properties

The channel binding tokens generated are of the type "tls-server-end-point" as defined in RFC 5929.

+ +
  • {@systemProperty jdk.http.maxHeaderSize} (default: 393216 or 384kB)
    + This is the maximum header field section size that a client is prepared to accept. + This is computed as the sum of the size of the uncompressed header name, plus + the size of the uncompressed header value, plus an overhead of 32 bytes for + each field section line. If a peer sends a field section that exceeds this + size a {@link java.net.ProtocolException ProtocolException} will be raised. + This applies to all versions of the HTTP protocol. A value of zero or a negative + value means no limit. If left unspecified, the default value is 393216 bytes.

    All these properties are checked only once at startup.

    diff --git a/src/java.base/share/classes/java/text/MessageFormat.java b/src/java.base/share/classes/java/text/MessageFormat.java index e54033cb8ff..ce2471350b2 100644 --- a/src/java.base/share/classes/java/text/MessageFormat.java +++ b/src/java.base/share/classes/java/text/MessageFormat.java @@ -41,6 +41,7 @@ import java.io.InvalidObjectException; import java.io.IOException; import java.io.ObjectInputStream; +import java.io.ObjectStreamException; import java.text.DecimalFormat; import java.util.ArrayList; import java.util.Arrays; @@ -982,6 +983,8 @@ public Object[] parse(String source, ParsePosition pos) { maximumArgumentNumber = argumentNumbers[i]; } } + + // Constructors/applyPattern ensure that resultArray.length < MAX_ARGUMENT_INDEX Object[] resultArray = new Object[maximumArgumentNumber + 1]; int patternOffset = 0; @@ -1232,6 +1235,9 @@ protected Object readResolve() throws InvalidObjectException { * @serial */ private int[] argumentNumbers = new int[INITIAL_FORMATS]; + // Implementation limit for ArgumentIndex pattern element. Valid indices must + // be less than this value + private static final int MAX_ARGUMENT_INDEX = 10000; /** * One less than the number of entries in offsets. Can also be thought of @@ -1456,6 +1462,11 @@ private void makeFormat(int position, int offsetNumber, + argumentNumber); } + if (argumentNumber >= MAX_ARGUMENT_INDEX) { + throw new IllegalArgumentException( + argumentNumber + " exceeds the ArgumentIndex implementation limit"); + } + // resize format information arrays if necessary if (offsetNumber >= formats.length) { int newLength = formats.length * 2; @@ -1602,24 +1613,52 @@ private static final void copyAndFixQuotes(String source, int start, int end, * @throws InvalidObjectException if the objects read from the stream is invalid. */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - boolean isValid = maxOffset >= -1 - && formats.length > maxOffset - && offsets.length > maxOffset - && argumentNumbers.length > maxOffset; + ObjectInputStream.GetField fields = in.readFields(); + if (fields.defaulted("argumentNumbers") || fields.defaulted("offsets") + || fields.defaulted("formats") || fields.defaulted("locale") + || fields.defaulted("pattern") || fields.defaulted("maxOffset")){ + throw new InvalidObjectException("Stream has missing data"); + } + + locale = (Locale) fields.get("locale", null); + String patt = (String) fields.get("pattern", null); + int maxOff = fields.get("maxOffset", -2); + int[] argNums = ((int[]) fields.get("argumentNumbers", null)).clone(); + int[] offs = ((int[]) fields.get("offsets", null)).clone(); + Format[] fmts = ((Format[]) fields.get("formats", null)).clone(); + + // Check arrays/maxOffset have correct value/length + boolean isValid = maxOff >= -1 && argNums.length > maxOff + && offs.length > maxOff && fmts.length > maxOff; + + // Check the correctness of arguments and offsets if (isValid) { - int lastOffset = pattern.length() + 1; - for (int i = maxOffset; i >= 0; --i) { - if ((offsets[i] < 0) || (offsets[i] > lastOffset)) { + int lastOffset = patt.length() + 1; + for (int i = maxOff; i >= 0; --i) { + if (argNums[i] < 0 || argNums[i] >= MAX_ARGUMENT_INDEX + || offs[i] < 0 || offs[i] > lastOffset) { isValid = false; break; } else { - lastOffset = offsets[i]; + lastOffset = offs[i]; } } } + if (!isValid) { - throw new InvalidObjectException("Could not reconstruct MessageFormat from corrupt stream."); + throw new InvalidObjectException("Stream has invalid data"); } + maxOffset = maxOff; + pattern = patt; + offsets = offs; + formats = fmts; + argumentNumbers = argNums; + } + + /** + * Serialization without data not supported for this class. + */ + private void readObjectNoData() throws ObjectStreamException { + throw new InvalidObjectException("Deserialized MessageFormat objects need data"); } } diff --git a/src/java.base/share/classes/jdk/internal/event/EventHelper.java b/src/java.base/share/classes/jdk/internal/event/EventHelper.java index 31103b46e94..d078f3fe54c 100644 --- a/src/java.base/share/classes/jdk/internal/event/EventHelper.java +++ b/src/java.base/share/classes/jdk/internal/event/EventHelper.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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,7 @@ import jdk.internal.misc.JavaUtilJarAccess; import jdk.internal.misc.SharedSecrets; +import jdk.internal.misc.ThreadTracker; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; @@ -130,6 +131,18 @@ private static String getDurationString(Instant start) { } } + private static class ThreadTrackHolder { + static final ThreadTracker TRACKER = new ThreadTracker(); + } + + private static Object tryBeginLookup() { + return ThreadTrackHolder.TRACKER.tryBegin(); + } + + private static void endLookup(Object key) { + ThreadTrackHolder.TRACKER.end(key); + } + /** * Helper to determine if security events are being logged * at a preconfigured logging level. The configuration value @@ -138,14 +151,20 @@ private static String getDurationString(Instant start) { * @return boolean indicating whether an event should be logged */ public static boolean isLoggingSecurity() { - // Avoid a bootstrap issue where the commitEvent attempts to - // trigger early loading of System Logger but where - // the verification process still has JarFiles locked - if (securityLogger == null && !JUJA.isInitializing()) { - LOGGER_HANDLE.compareAndSet( null, System.getLogger(SECURITY_LOGGER_NAME)); - loggingSecurity = securityLogger.isLoggable(LOG_LEVEL); + Object key; + // Avoid bootstrap issues where + // * commitEvent triggers early loading of System Logger but where + // the verification process still has JarFiles locked + // * the loading of the logging libraries involves recursive + // calls to security libraries triggering recursion + if (securityLogger == null && !JUJA.isInitializing() && (key = tryBeginLookup()) != null) { + try { + LOGGER_HANDLE.compareAndSet(null, System.getLogger(SECURITY_LOGGER_NAME)); + loggingSecurity = securityLogger.isLoggable(LOG_LEVEL); + } finally { + endLookup(key); + } } return loggingSecurity; } - } diff --git a/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java b/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java index cbb4dbc827e..224bb9732f8 100644 --- a/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java +++ b/src/java.base/share/classes/jdk/internal/loader/URLClassPath.java @@ -210,7 +210,9 @@ public URLClassPath(URL[] urls, AccessControlContext acc) { this.unopenedUrls = unopenedUrls; this.path = path; - this.jarHandler = null; + // the application class loader uses the built-in protocol handler to avoid protocol + // handler lookup when opening JAR files on the class path. + this.jarHandler = new sun.net.www.protocol.jar.Handler(); this.acc = null; } diff --git a/src/java.base/share/classes/jdk/internal/misc/ThreadTracker.java b/src/java.base/share/classes/jdk/internal/misc/ThreadTracker.java new file mode 100644 index 00000000000..fb0f3bcab20 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/misc/ThreadTracker.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021, 2022, 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 jdk.internal.misc; + +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; + +/** + * Tracks threads to help detect reentrancy without using ThreadLocal variables. + * A thread invokes the {@code begin} or {@code tryBegin} methods at the start + * of a block, and the {@code end} method at the end of a block. + */ +public class ThreadTracker { + + /** + * A reference to a Thread that is suitable for use as a key in a collection. + * The hashCode/equals methods do not invoke the Thread hashCode/equals method + * as they may run arbitrary code and/or leak references to Thread objects. + */ + private final class ThreadRef { + private final Thread thread; + + ThreadRef(Thread thread) { + this.thread = thread; + } + + Thread thread() { + return this.thread; + } + + @Override + public int hashCode() { + return Long.hashCode(thread.getId()); + } + @Override + public boolean equals(Object obj) { + return (obj instanceof ThreadRef) + && this.thread == ((ThreadRef)obj).thread; + } + } + + private final Set threads = ConcurrentHashMap.newKeySet(); + + /** + * Adds the current thread to thread set if not already in the set. + * Returns a key to remove the thread or {@code null} if already in the set. + */ + public Object tryBegin() { + var threadRef = new ThreadRef(Thread.currentThread()); + return threads.add(threadRef) ? threadRef : null; + } + + /** + * Adds the current thread to thread set if not already in the set. + * Returns a key to remove the thread. + */ + public Object begin() { + var threadRef = new ThreadRef(Thread.currentThread()); + boolean added = threads.add(threadRef); + assert added; + return threadRef; + } + + /** + * Removes the thread identified by the key from the thread set. + */ + public void end(Object key) { + var threadRef = (ThreadRef) key; + assert threadRef.thread() == Thread.currentThread(); + boolean removed = threads.remove(threadRef); + assert removed; + } + + /** + * Returns true if the given thread is tracked. + */ + public boolean contains(Thread thread) { + var threadRef = new ThreadRef(thread); + return threads.contains(threadRef); + } +} diff --git a/src/java.base/share/classes/sun/launcher/LauncherHelper.java b/src/java.base/share/classes/sun/launcher/LauncherHelper.java index e8b7dd4693a..d07f3159543 100644 --- a/src/java.base/share/classes/sun/launcher/LauncherHelper.java +++ b/src/java.base/share/classes/sun/launcher/LauncherHelper.java @@ -167,7 +167,7 @@ static void showSettings(boolean printToStderr, String optionFlag, printProperties(); break; case "locale": - printLocale(); + printLocale(false); break; case "system": if (System.getProperty("os.name").contains("Linux")) { @@ -177,7 +177,7 @@ static void showSettings(boolean printToStderr, String optionFlag, default: printVmSettings(initialHeapSize, maxHeapSize, stackSize); printProperties(); - printLocale(); + printLocale(true); if (System.getProperty("os.name").contains("Linux")) { printSystemMetrics(); } @@ -272,9 +272,15 @@ private static void printPropertyValue(String key, String value) { /* * prints the locale subopt/section */ - private static void printLocale() { + private static void printLocale(boolean summaryMode) { Locale locale = Locale.getDefault(); - ostream.println(LOCALE_SETTINGS); + if (!summaryMode) { + ostream.println(LOCALE_SETTINGS); + } else { + ostream.println("Locale settings summary:"); + ostream.println(INDENT + "Use \"-XshowSettings:locale\" " + + "option for verbose locale settings options"); + } ostream.println(INDENT + "default locale = " + locale.getDisplayName()); ostream.println(INDENT + "default display locale = " + @@ -283,7 +289,9 @@ private static void printLocale() { Locale.getDefault(Category.FORMAT).getDisplayName()); ostream.println(INDENT + "tzdata version = " + ZoneInfoFile.getVersion()); - printLocales(); + if (!summaryMode) { + printLocales(); + } ostream.println(); } diff --git a/src/java.base/share/classes/sun/net/www/MessageHeader.java b/src/java.base/share/classes/sun/net/www/MessageHeader.java index 95b82cda283..664e7ec0d33 100644 --- a/src/java.base/share/classes/sun/net/www/MessageHeader.java +++ b/src/java.base/share/classes/sun/net/www/MessageHeader.java @@ -30,6 +30,8 @@ package sun.net.www; import java.io.*; +import java.lang.reflect.Array; +import java.net.ProtocolException; import java.util.Collections; import java.util.*; @@ -46,11 +48,32 @@ class MessageHeader { private String values[]; private int nkeys; + // max number of bytes for headers, <=0 means unlimited; + // this corresponds to the length of the names, plus the length + // of the values, plus an overhead of 32 bytes per name: value + // pair. + // Note: we use the same definition as HTTP/2 SETTINGS_MAX_HEADER_LIST_SIZE + // see RFC 9113, section 6.5.2. + // https://www.rfc-editor.org/rfc/rfc9113.html#SETTINGS_MAX_HEADER_LIST_SIZE + private final int maxHeaderSize; + + // Aggregate size of the field lines (name + value + 32) x N + // that have been parsed and accepted so far. + // This is defined as a long to force promotion to long + // and avoid overflows; see checkNewSize; + private long size; + public MessageHeader () { + this(0); + } + + public MessageHeader (int maxHeaderSize) { + this.maxHeaderSize = maxHeaderSize; grow(); } public MessageHeader (InputStream is) throws java.io.IOException { + maxHeaderSize = 0; parseHeader(is); } @@ -466,10 +489,28 @@ public static String canonicalID(String id) { public void parseHeader(InputStream is) throws java.io.IOException { synchronized (this) { nkeys = 0; + size = 0; } mergeHeader(is); } + private void checkMaxHeaderSize(int sz) throws ProtocolException { + if (maxHeaderSize > 0) checkNewSize(size, sz, 0); + } + + private long checkNewSize(long size, int name, int value) throws ProtocolException { + // See SETTINGS_MAX_HEADER_LIST_SIZE, RFC 9113, section 6.5.2. + long newSize = size + name + value + 32; + if (maxHeaderSize > 0 && newSize > maxHeaderSize) { + Arrays.fill(keys, 0, nkeys, null); + Arrays.fill(values,0, nkeys, null); + nkeys = 0; + throw new ProtocolException(String.format("Header size too big: %s > %s", + newSize, maxHeaderSize)); + } + return newSize; + } + /** Parse and merge a MIME header from an input stream. */ @SuppressWarnings("fallthrough") public void mergeHeader(InputStream is) throws java.io.IOException { @@ -483,7 +524,15 @@ public void mergeHeader(InputStream is) throws java.io.IOException { int c; boolean inKey = firstc > ' '; s[len++] = (char) firstc; + checkMaxHeaderSize(len); parseloop:{ + // We start parsing for a new name value pair here. + // The max header size includes an overhead of 32 bytes per + // name value pair. + // See SETTINGS_MAX_HEADER_LIST_SIZE, RFC 9113, section 6.5.2. + long maxRemaining = maxHeaderSize > 0 + ? maxHeaderSize - size - 32 + : Long.MAX_VALUE; while ((c = is.read()) >= 0) { switch (c) { case ':': @@ -517,6 +566,9 @@ public void mergeHeader(InputStream is) throws java.io.IOException { s = ns; } s[len++] = (char) c; + if (maxHeaderSize > 0 && len > maxRemaining) { + checkMaxHeaderSize(len); + } } firstc = -1; } @@ -538,6 +590,9 @@ public void mergeHeader(InputStream is) throws java.io.IOException { v = new String(); else v = String.copyValueOf(s, keyend, len - keyend); + int klen = k == null ? 0 : k.length(); + + size = checkNewSize(size, klen, v.length()); add(k, v); } } diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 9aaee966828..8840d0c5e58 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -169,6 +169,8 @@ public class HttpURLConnection extends java.net.HttpURLConnection { */ private static int bufSize4ES = 0; + private static final int maxHeaderSize; + /* * Restrict setting of request headers through the public api * consistent with JavaScript XMLHttpRequest2 with a few @@ -282,6 +284,19 @@ private static Set schemesListToSet(String list) { } else { restrictedHeaderSet = null; } + + int defMaxHeaderSize = 384 * 1024; + String maxHeaderSizeStr = getNetProperty("jdk.http.maxHeaderSize"); + int maxHeaderSizeVal = defMaxHeaderSize; + if (maxHeaderSizeStr != null) { + try { + maxHeaderSizeVal = Integer.parseInt(maxHeaderSizeStr); + } catch (NumberFormatException n) { + maxHeaderSizeVal = defMaxHeaderSize; + } + } + if (maxHeaderSizeVal < 0) maxHeaderSizeVal = 0; + maxHeaderSize = maxHeaderSizeVal; } static final String httpVersion = "HTTP/1.1"; @@ -724,7 +739,7 @@ private void writeRequests() throws IOException { } ps = (PrintStream) http.getOutputStream(); connected=true; - responses = new MessageHeader(); + responses = new MessageHeader(maxHeaderSize); setRequests=false; writeRequests(); } @@ -879,7 +894,7 @@ protected HttpURLConnection(URL u, Proxy p, Handler handler) throws IOException { super(checkURL(u)); requests = new MessageHeader(); - responses = new MessageHeader(); + responses = new MessageHeader(maxHeaderSize); userHeaders = new MessageHeader(); this.handler = handler; instProxy = p; @@ -2766,7 +2781,7 @@ private boolean followRedirect0(String loc, int stat, URL locUrl) } // clear out old response headers!!!! - responses = new MessageHeader(); + responses = new MessageHeader(maxHeaderSize); if (stat == HTTP_USE_PROXY) { /* This means we must re-request the resource through the * proxy denoted in the "Location:" field of the response. @@ -2955,7 +2970,7 @@ private void reset() throws IOException { } catch (IOException e) { } } responseCode = -1; - responses = new MessageHeader(); + responses = new MessageHeader(maxHeaderSize); connected = false; } diff --git a/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java b/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java index 1b35ba18625..8d4567dc66b 100644 --- a/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java +++ b/src/java.base/share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java @@ -82,6 +82,9 @@ public final class RSAPrivateCrtKeyImpl */ public static RSAPrivateKey newKey(KeyType type, String format, byte[] encoded) throws InvalidKeyException { + if (format == null || encoded == null || encoded.length == 0) { + throw new InvalidKeyException("Missing key encoding"); + } switch (format) { case "PKCS#8": RSAPrivateCrtKeyImpl key = new RSAPrivateCrtKeyImpl(encoded); @@ -154,10 +157,6 @@ public static RSAPrivateKey newKey(KeyType type, * Construct a key from its encoding. Called from newKey above. */ private RSAPrivateCrtKeyImpl(byte[] encoded) throws InvalidKeyException { - if (encoded == null || encoded.length == 0) { - throw new InvalidKeyException("Missing key encoding"); - } - decode(encoded); RSAKeyFactory.checkRSAProviderKeyLengths(n.bitLength(), e); try { diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java index d7fce6b1d5b..4d19043ac69 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java +++ b/src/java.base/share/classes/sun/security/ssl/CertificateMessage.java @@ -388,7 +388,7 @@ private void onCertificate(ServerHandshakeContext shc, ClientAuthType.CLIENT_AUTH_REQUESTED) { // unexpected or require client authentication throw shc.conContext.fatal(Alert.BAD_CERTIFICATE, - "Empty server certificate chain"); + "Empty client certificate chain"); } else { return; } @@ -405,7 +405,7 @@ private void onCertificate(ServerHandshakeContext shc, } } catch (CertificateException ce) { throw shc.conContext.fatal(Alert.BAD_CERTIFICATE, - "Failed to parse server certificates", ce); + "Failed to parse client certificates", ce); } checkClientCerts(shc, x509Certs); @@ -1253,7 +1253,7 @@ private static X509Certificate[] checkClientCerts( } } catch (CertificateException ce) { throw shc.conContext.fatal(Alert.BAD_CERTIFICATE, - "Failed to parse server certificates", ce); + "Failed to parse client certificates", ce); } // find out the types of client authentication used diff --git a/src/java.base/share/classes/sun/security/ssl/ClientHello.java b/src/java.base/share/classes/sun/security/ssl/ClientHello.java index 5768da93745..a5d0ac94b33 100644 --- a/src/java.base/share/classes/sun/security/ssl/ClientHello.java +++ b/src/java.base/share/classes/sun/security/ssl/ClientHello.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -218,8 +218,6 @@ byte[] getHelloCookieBytes() { // ignore cookie hos.putBytes16(getEncodedCipherSuites()); hos.putBytes8(compressionMethod); - extensions.send(hos); // In TLS 1.3, use of certain - // extensions is mandatory. } catch (IOException ioe) { // unlikely } @@ -905,8 +903,8 @@ private ProtocolVersion negotiateProtocol( throw context.conContext.fatal(Alert.PROTOCOL_VERSION, "The client supported protocol versions " + Arrays.toString( ProtocolVersion.toStringArray(clientSupportedVersions)) + - " are not accepted by server preferences " + - context.activeProtocols); + " are not accepted by server preferences " + Arrays.toString( + ProtocolVersion.toStringArray(context.activeProtocols))); } } @@ -1390,6 +1388,9 @@ public void consume(ConnectionContext context, shc.handshakeProducers.put(SSLHandshake.SERVER_HELLO.id, SSLHandshake.SERVER_HELLO); + // Reset the ClientHello non-zero offset fragment allowance + shc.acceptCliHelloFragments = false; + // // produce // diff --git a/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java b/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java index 0aee1f4035a..14e8db6ed71 100644 --- a/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java +++ b/src/java.base/share/classes/sun/security/ssl/DTLSInputRecord.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -28,13 +28,7 @@ import java.io.IOException; import java.nio.ByteBuffer; import java.security.GeneralSecurityException; -import java.util.Collections; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Set; -import java.util.TreeSet; +import java.util.*; import javax.crypto.BadPaddingException; import javax.net.ssl.SSLException; import javax.net.ssl.SSLProtocolException; @@ -46,12 +40,23 @@ final class DTLSInputRecord extends InputRecord implements DTLSRecord { private DTLSReassembler reassembler = null; private int readEpoch; + private SSLContextImpl sslContext; DTLSInputRecord(HandshakeHash handshakeHash) { super(handshakeHash, SSLReadCipher.nullDTlsReadCipher()); this.readEpoch = 0; } + // Method to set TransportContext + public void setTransportContext(TransportContext tc) { + this.tc = tc; + } + + // Method to set SSLContext + public void setSSLContext(SSLContextImpl sslContext) { + this.sslContext = sslContext; + } + @Override void changeReadCiphers(SSLReadCipher readCipher) { this.readCipher = readCipher; @@ -544,6 +549,27 @@ public int compareTo(RecordFragment o) { } } + /** + * Turn a sufficiently-large initial ClientHello fragment into one that + * stops immediately after the compression methods. This is only used + * for the initial CH message fragment at offset 0. + * + * @param srcFrag the fragment actually received by the DTLSReassembler + * @param limit the size of the new, cloned/truncated handshake fragment + * + * @return a truncated handshake fragment that is sized to look like a + * complete message, but actually contains only up to the compression + * methods (no extensions) + */ + private static HandshakeFragment truncateChFragment(HandshakeFragment srcFrag, + int limit) { + return new HandshakeFragment(Arrays.copyOf(srcFrag.fragment, limit), + srcFrag.contentType, srcFrag.majorVersion, + srcFrag.minorVersion, srcFrag.recordEnS, srcFrag.recordEpoch, + srcFrag.recordSeq, srcFrag.handshakeType, limit, + srcFrag.messageSeq, srcFrag.fragmentOffset, limit); + } + private static final class HoleDescriptor { int offset; // fragment_offset int limit; // fragment_offset + fragment_length @@ -647,10 +673,17 @@ void expectingFinishFlight() { // Queue up a handshake message. void queueUpHandshake(HandshakeFragment hsf) throws SSLProtocolException { if (!isDesirable(hsf)) { - // Not a dedired record, discard it. + // Not a desired record, discard it. return; } + if (hsf.handshakeType == SSLHandshake.CLIENT_HELLO.id) { + // validate the first or subsequent ClientHello message + if ((hsf = valHello(hsf, hsf.messageSeq == 0)) == null) { + return; + } + } + // Clean up the retransmission messages if necessary. cleanUpRetransmit(hsf); @@ -783,6 +816,100 @@ void queueUpHandshake(HandshakeFragment hsf) throws SSLProtocolException { } } + private HandshakeFragment valHello(HandshakeFragment hsf, + boolean firstHello) { + ServerHandshakeContext shc = + (ServerHandshakeContext) tc.handshakeContext; + // Drop any fragment that is not a zero offset until we've received + // a second (or possibly later) CH message that passes the cookie + // check. + if (shc == null || !shc.acceptCliHelloFragments) { + if (hsf.fragmentOffset != 0) { + return null; + } + } else { + // Let this fragment through to the DTLSReassembler as-is + return hsf; + } + + try { + ByteBuffer fragmentData = ByteBuffer.wrap(hsf.fragment); + + ProtocolVersion pv = ProtocolVersion.valueOf( + Record.getInt16(fragmentData)); + if (!pv.isDTLS) { + return null; + } + // Read the random (32 bytes) + if (fragmentData.remaining() < 32) { + if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { + SSLLogger.fine("Rejected client hello fragment (bad random len) " + + "fo=" + hsf.fragmentOffset + " fl=" + hsf.fragmentLength); + } + return null; + } + fragmentData.position(fragmentData.position() + 32); + + // SessionID + byte[] sessId = Record.getBytes8(fragmentData); + if (sessId.length > 0 && + !SSLConfiguration.enableDtlsResumeCookie) { + // If we are in a resumption it is possible that the cookie + // exchange will be skipped. This is a server-side setting + // and it is NOT the default. If enableDtlsResumeCookie is + // false though, then we will buffer fragments since there + // is no cookie exchange to execute prior to performing + // reassembly. + return hsf; + } + + // Cookie + byte[] cookie = Record.getBytes8(fragmentData); + if (firstHello && cookie.length != 0) { + if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { + SSLLogger.fine("Rejected initial client hello fragment (bad cookie len) " + + "fo=" + hsf.fragmentOffset + " fl=" + hsf.fragmentLength); + } + return null; + } + // CipherSuites + Record.getBytes16(fragmentData); + // Compression methods + Record.getBytes8(fragmentData); + + // If it's the first fragment, we'll truncate it and push it + // through the reassembler. + if (firstHello) { + return truncateChFragment(hsf, fragmentData.position()); + } else { + HelloCookieManager hcMgr = sslContext. + getHelloCookieManager(ProtocolVersion.DTLS10); + ByteBuffer msgFragBuf = ByteBuffer.wrap(hsf.fragment, 0, + fragmentData.position()); + ClientHello.ClientHelloMessage chMsg = + new ClientHello.ClientHelloMessage(shc, msgFragBuf, null); + if (!hcMgr.isCookieValid(shc, chMsg, cookie)) { + // Bad cookie check, truncate it and let the ClientHello + // consumer recheck, fail and take the appropriate action. + return truncateChFragment(hsf, fragmentData.position()); + } else { + // It's a good cookie, return the original handshake + // fragment and let it go into the DTLSReassembler like + // any other fragment so we can wait for the rest of + // the CH message. + shc.acceptCliHelloFragments = true; + return hsf; + } + } + } catch (IOException ioe) { + if (SSLLogger.isOn && SSLLogger.isOn("verbose")) { + SSLLogger.fine("Rejected client hello fragment " + + "fo=" + hsf.fragmentOffset + " fl=" + hsf.fragmentLength); + } + return null; + } + } + // Queue up a ChangeCipherSpec message void queueUpChangeCipherSpec(RecordFragment rf) throws SSLProtocolException { diff --git a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java index 4065391be72..e0dd1fd4399 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLSocketImpl.java @@ -1766,23 +1766,24 @@ private void closeSocket(boolean selfInitiated) throws IOException { if (conContext.inputRecord instanceof SSLSocketInputRecord && isConnected) { if (appInput.readLock.tryLock()) { - int soTimeout = getSoTimeout(); try { - // deplete could hang on the skip operation - // in case of infinite socket read timeout. - // Change read timeout to avoid deadlock. - // This workaround could be replaced later - // with the right synchronization - if (soTimeout == 0) { - setSoTimeout(DEFAULT_SKIP_TIMEOUT); + int soTimeout = getSoTimeout(); + try { + // deplete could hang on the skip operation + // in case of infinite socket read timeout. + // Change read timeout to avoid deadlock. + // This workaround could be replaced later + // with the right synchronization + if (soTimeout == 0) + setSoTimeout(DEFAULT_SKIP_TIMEOUT); + ((SSLSocketInputRecord) (conContext.inputRecord)).deplete(false); + } catch (java.net.SocketTimeoutException stEx) { + // skip timeout exception during deplete + } finally { + if (soTimeout == 0) + setSoTimeout(soTimeout); } - ((SSLSocketInputRecord) (conContext.inputRecord)).deplete(false); - } catch (java.net.SocketTimeoutException stEx) { - // skip timeout exception during deplete } finally { - if (soTimeout == 0) { - setSoTimeout(soTimeout); - } appInput.readLock.unlock(); } } diff --git a/src/java.base/share/classes/sun/security/ssl/ServerHandshakeContext.java b/src/java.base/share/classes/sun/security/ssl/ServerHandshakeContext.java index cb2a812430f..01c9e6b1ec3 100644 --- a/src/java.base/share/classes/sun/security/ssl/ServerHandshakeContext.java +++ b/src/java.base/share/classes/sun/security/ssl/ServerHandshakeContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -55,6 +55,7 @@ class ServerHandshakeContext extends HandshakeContext { CertificateMessage.CertificateEntry currentCertEntry; private static final long DEFAULT_STATUS_RESP_DELAY = 5000L; final long statusRespTimeout; + boolean acceptCliHelloFragments = false; ServerHandshakeContext(SSLContextImpl sslContext, diff --git a/src/java.base/share/classes/sun/security/ssl/TransportContext.java b/src/java.base/share/classes/sun/security/ssl/TransportContext.java index be3f480ae1f..4c1b1c2df82 100644 --- a/src/java.base/share/classes/sun/security/ssl/TransportContext.java +++ b/src/java.base/share/classes/sun/security/ssl/TransportContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -138,6 +138,12 @@ private TransportContext(SSLContextImpl sslContext, SSLTransport transport, this.acc = AccessController.getContext(); this.consumers = new HashMap<>(); + + if (inputRecord instanceof DTLSInputRecord) { + DTLSInputRecord dtlsInputRecord = (DTLSInputRecord)inputRecord; + dtlsInputRecord.setTransportContext(this); + dtlsInputRecord.setSSLContext(this.sslContext); + } } // Dispatch plaintext to a specific consumer. diff --git a/src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java b/src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java index 0aaa44978d2..39aecc27ecd 100644 --- a/src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java +++ b/src/java.base/share/classes/sun/security/validator/CADistrustPolicy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -53,6 +53,22 @@ void checkDistrust(String variant, X509Certificate[] chain) } SymantecTLSPolicy.checkDistrust(chain); } + }, + + /** + * Distrust TLS Server certificates anchored by an Entrust root CA and + * issued after November 11, 2024. If enabled, this policy is currently + * enforced by the PKIX and SunX509 TrustManager implementations + * of the SunJSSE provider implementation. + */ + ENTRUST_TLS { + void checkDistrust(String variant, X509Certificate[] chain) + throws ValidatorException { + if (!variant.equals(Validator.VAR_TLS_SERVER)) { + return; + } + EntrustTLSPolicy.checkDistrust(chain); + } }; /** diff --git a/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java b/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java new file mode 100644 index 00000000000..a19c2e5039d --- /dev/null +++ b/src/java.base/share/classes/sun/security/validator/EntrustTLSPolicy.java @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2024, 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 sun.security.validator; + +import java.security.cert.X509Certificate; +import java.time.LocalDate; +import java.time.Month; +import java.time.ZoneOffset; +import java.util.Date; +import java.util.Map; +import java.util.Set; + +import sun.security.util.Debug; +import sun.security.x509.X509CertImpl; + +/** + * This class checks if Entrust issued TLS Server certificates should be + * restricted. + */ +final class EntrustTLSPolicy { + + private static final Debug debug = Debug.getInstance("certpath"); + + // SHA-256 certificate fingerprints of distrusted roots + private static final Set FINGERPRINTS = Set.of( + // cacerts alias: entrustevca + // DN: CN=Entrust Root Certification Authority, + // OU=(c) 2006 Entrust, Inc., + // OU=www.entrust.net/CPS is incorporated by reference, + // O=Entrust, Inc., C=US + "73C176434F1BC6D5ADF45B0E76E727287C8DE57616C1E6E6141A2B2CBC7D8E4C", + // cacerts alias: entrustrootcaec1 + // DN: CN=Entrust Root Certification Authority - EC1, + // OU=(c) 2012 Entrust, Inc. - for authorized use only, + // OU=See www.entrust.net/legal-terms, O=Entrust, Inc., C=US + "02ED0EB28C14DA45165C566791700D6451D7FB56F0B2AB1D3B8EB070E56EDFF5", + // cacerts alias: entrustrootcag2 + // DN: CN=Entrust Root Certification Authority - G2, + // OU=(c) 2009 Entrust, Inc. - for authorized use only, + // OU=See www.entrust.net/legal-terms, O=Entrust, Inc., C=US + "43DF5774B03E7FEF5FE40D931A7BEDF1BB2E6B42738C4E6D3841103D3AA7F339", + // cacerts alias: entrustrootcag4 + // DN: CN=Entrust Root Certification Authority - G4 + // OU=(c) 2015 Entrust, Inc. - for authorized use only, + // OU=See www.entrust.net/legal-terms, O=Entrust, Inc., C=US, + "DB3517D1F6732A2D5AB97C533EC70779EE3270A62FB4AC4238372460E6F01E88", + // cacerts alias: entrust2048ca + // DN: CN=Entrust.net Certification Authority (2048), + // OU=(c) 1999 Entrust.net Limited, + // OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), + // O=Entrust.net + "6DC47172E01CBCB0BF62580D895FE2B8AC9AD4F873801E0C10B9C837D21EB177", + // cacerts alias: affirmtrustcommercialca + // DN: CN=AffirmTrust Commercial, O=AffirmTrust, C=US + "0376AB1D54C5F9803CE4B2E201A0EE7EEF7B57B636E8A93C9B8D4860C96F5FA7", + // cacerts alias: affirmtrustnetworkingca + // DN: CN=AffirmTrust Networking, O=AffirmTrust, C=US + "0A81EC5A929777F145904AF38D5D509F66B5E2C58FCDB531058B0E17F3F0B41B", + // cacerts alias: affirmtrustpremiumca + // DN: CN=AffirmTrust Premium, O=AffirmTrust, C=US + "70A73F7F376B60074248904534B11482D5BF0E698ECC498DF52577EBF2E93B9A", + // cacerts alias: affirmtrustpremiumeccca + // DN: CN=AffirmTrust Premium ECC, O=AffirmTrust, C=US + "BD71FDF6DA97E4CF62D1647ADD2581B07D79ADF8397EB4ECBA9C5E8488821423" + ); + + // Any TLS Server certificate that is anchored by one of the Entrust + // roots above and is issued after this date will be distrusted. + private static final LocalDate NOVEMBER_11_2024 = + LocalDate.of(2024, Month.NOVEMBER, 11); + + /** + * This method assumes the eeCert is a TLS Server Cert and chains back to + * the anchor. + * + * @param chain the end-entity's certificate chain. The end entity cert + * is at index 0, the trust anchor at index n-1. + * @throws ValidatorException if the certificate is distrusted + */ + static void checkDistrust(X509Certificate[] chain) + throws ValidatorException { + X509Certificate anchor = chain[chain.length-1]; + String fp = fingerprint(anchor); + if (fp == null) { + throw new ValidatorException("Cannot generate fingerprint for " + + "trust anchor of TLS server certificate"); + } + if (FINGERPRINTS.contains(fp)) { + Date notBefore = chain[0].getNotBefore(); + LocalDate ldNotBefore = LocalDate.ofInstant(notBefore.toInstant(), + ZoneOffset.UTC); + // reject if certificate is issued after November 11, 2024 + checkNotBefore(ldNotBefore, NOVEMBER_11_2024, anchor); + } + } + + private static String fingerprint(X509Certificate cert) { + return X509CertImpl.getFingerprint("SHA-256", cert); + } + + private static void checkNotBefore(LocalDate notBeforeDate, + LocalDate distrustDate, X509Certificate anchor) + throws ValidatorException { + if (notBeforeDate.isAfter(distrustDate)) { + throw new ValidatorException + ("TLS Server certificate issued after " + distrustDate + + " and anchored by a distrusted legacy Entrust root CA: " + + anchor.getSubjectX500Principal(), + ValidatorException.T_UNTRUSTED_CERT, anchor); + } + } + + private EntrustTLSPolicy() {} +} diff --git a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties index c231cadc416..3ed4f873a3c 100644 --- a/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties +++ b/src/java.base/share/classes/sun/util/resources/CurrencyNames.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2024, 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 @@ -284,6 +284,7 @@ ZAR=ZAR ZMK=ZMK ZMW=ZMW ZWD=ZWD +ZWG=ZWG ZWL=ZWL ZWN=ZWN ZWR=ZWR @@ -509,5 +510,6 @@ yum=Yugoslavian New Dinar (1994-2002) zar=South African Rand zmk=Zambian Kwacha zwd=Zimbabwean Dollar (1980-2008) +zwg=Zimbabwe Gold zwl=Zimbabwean Dollar (2009) zwr=Zimbabwean Dollar (2008) diff --git a/src/java.base/share/conf/net.properties b/src/java.base/share/conf/net.properties index 6bc00e464b6..3f53c7aaab2 100644 --- a/src/java.base/share/conf/net.properties +++ b/src/java.base/share/conf/net.properties @@ -137,3 +137,20 @@ jdk.http.auth.tunneling.disabledSchemes=Basic #jdk.http.ntlm.transparentAuth=trustedHosts # jdk.http.ntlm.transparentAuth=disabled + +# +# Maximum HTTP field section size that a client is prepared to accept +# +# jdk.http.maxHeaderSize=393216 +# +# This is the maximum header field section size that a client is prepared to accept. +# This is computed as the sum of the size of the uncompressed header name, plus +# the size of the uncompressed header value, plus an overhead of 32 bytes for +# each field section line. If a peer sends a field section that exceeds this +# size a {@link java.net.ProtocolException ProtocolException} will be raised. +# This applies to all versions of the HTTP protocol. A value of zero or a negative +# value means no limit. If left unspecified, the default value is 393216 bytes +# or 384kB. +# +# Note: This property is currently used by the JDK Reference implementation. It +# is not guaranteed to be examined and used by other implementations. diff --git a/src/java.base/share/conf/security/java.security b/src/java.base/share/conf/security/java.security index 087b81b9fe9..6f3f5448b93 100644 --- a/src/java.base/share/conf/security/java.security +++ b/src/java.base/share/conf/security/java.security @@ -758,6 +758,7 @@ jdk.jar.disabledAlgorithms=MD2, MD5, RSA keySize < 1024, \ # rsa_pkcs1_sha1, secp224r1 jdk.tls.disabledAlgorithms=SSLv3, TLSv1, TLSv1.1, DTLSv1.0, RC4, DES, \ MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL, \ + ECDH, \ include jdk.disabled.namedCurves # @@ -1286,6 +1287,9 @@ jdk.sasl.disabledMechanisms= # A4FE7C7F15155F3F0AEF7AAA83CF6E06DEB97CA3F909DF920AC1490882D488ED # Distrust after December 31, 2019. # +# ENTRUST_TLS : Distrust TLS Server certificates anchored by +# an Entrust root CA and issued after November 11, 2024. +# # Leading and trailing whitespace surrounding each value are ignored. # Unknown values are ignored. If the property is commented out or set to the # empty String, no policies are enforced. @@ -1297,7 +1301,7 @@ jdk.sasl.disabledMechanisms= # jdk.certpath.disabledAlgorithms; those restrictions are still enforced even # if this property is not enabled. # -jdk.security.caDistrustPolicies=SYMANTEC_TLS +jdk.security.caDistrustPolicies=SYMANTEC_TLS,ENTRUST_TLS # # FilePermission path canonicalization diff --git a/src/java.base/share/native/libjava/System.c b/src/java.base/share/native/libjava/System.c index e7b6a21fc92..59c269a1bdd 100644 --- a/src/java.base/share/native/libjava/System.c +++ b/src/java.base/share/native/libjava/System.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -198,7 +198,7 @@ Java_java_lang_System_initProperties(JNIEnv *env, jclass cla, jobject props) PUTPROP(props, "java.specification.version", VERSION_SPECIFICATION); PUTPROP(props, "java.specification.maintenance.version", - "2"); + "3"); PUTPROP(props, "java.specification.name", "Java Platform API Specification"); PUTPROP(props, "java.specification.vendor", diff --git a/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/src/java.base/unix/native/libnet/Inet6AddressImpl.c index e81ed8e0f29..71434522b58 100644 --- a/src/java.base/unix/native/libnet/Inet6AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet6AddressImpl.c @@ -170,7 +170,7 @@ lookupIfLocalhost(JNIEnv *env, const char *hostname, jboolean includeV6) result = (*env)->NewObjectArray(env, arraySize, ia_class, NULL); if (!result) goto done; - if ((*env)->GetStaticBooleanField(env, ia_class, ia_preferIPv6AddressID)) { + if ((*env)->GetStaticIntField(env, ia_class, ia_preferIPv6AddressID) == java_net_InetAddress_PREFER_IPV6_VALUE) { i = includeLoopback ? addrs6 : (addrs6 - numV6Loopbacks); j = 0; } else { diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 3446f0db2b4..898f52a8c35 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -439,7 +439,7 @@ protected void initializeDesktopProperties() { desktopProperties.put("awt.mouse.numButtons", BUTTONS); // These DnD properties must be set, otherwise Swing ends up spewing NPEs - // all over the place. The values came straight off of MToolkit. + // all over the place. The values came straight off of XToolkit. desktopProperties.put("DnD.Autoscroll.initialDelay", Integer.valueOf(50)); desktopProperties.put("DnD.Autoscroll.interval", Integer.valueOf(50)); desktopProperties.put("DnD.Autoscroll.cursorHysteresis", Integer.valueOf(5)); diff --git a/src/java.desktop/share/classes/java/awt/Robot.java b/src/java.desktop/share/classes/java/awt/Robot.java index e801639358c..9ad38ae992b 100644 --- a/src/java.desktop/share/classes/java/awt/Robot.java +++ b/src/java.desktop/share/classes/java/awt/Robot.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, 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 @@ -68,6 +68,43 @@ *

    * Applications that use Robot for purposes other than self-testing should * handle these error conditions gracefully. + *

    + * Platforms and desktop environments may impose restrictions or limitations + * on the access required to implement all functionality in the Robot class. + * For example: + *

      + *
    • preventing access to the contents of any part of a desktop + * or Window on the desktop that is not owned by the running application.
    • + *
    • treating window decorations as non-owned content.
    • + *
    • ignoring or limiting specific requests to manipulate windows.
    • + *
    • ignoring or limiting specific requests for Robot generated (synthesized) + * events related to keyboard and mouse etc.
    • + *
    • requiring specific or global permissions to any access to window + * contents, even application owned content,or to perform even limited + * synthesizing of events.
    • + *
    + * + * The Robot API specification requires that approvals for these be granted + * for full operation. + * If they are not granted, the API will be degraded as discussed here. + * Relevant specific API methods may document more specific limitations + * and requirements. + * Depending on the policies of the desktop environment, + * the approvals mentioned above may: + *
      + *
    • be required every time
    • + *
    • or persistent for the lifetime of an application,
    • + *
    • or persistent across multiple user desktop sessions
    • + *
    • be fine-grained permissions
    • + *
    • be associated with a specific binary application, + * or a class of binary applications.
    • + *
    + * + * When such approvals need to given interactively, it may impede the normal + * operation of the application until approved, and if approval is denied + * or not possible, or cannot be made persistent then it will degrade + * the functionality of this class and in turn any part of the operation + * of the application which is dependent on it. * * @author Robi Khan * @since 1.3 @@ -180,6 +217,11 @@ private void checkIsScreenDevice(GraphicsDevice device) { /** * Moves mouse pointer to given screen coordinates. + *

    + * The mouse pointer may not visually move on some platforms, + * while the subsequent mousePress and mouseRelease can be + * delivered to the correct location + * * @param x X position * @param y Y position */ @@ -374,8 +416,22 @@ private void checkKeycodeArgument(int keycode) { /** * Returns the color of a pixel at the given screen coordinates. + *

    + * If the desktop environment requires that permissions be granted + * to capture screen content, and the required permissions are not granted, + * then a {@code SecurityException} may be thrown, + * or the content of the returned {@code Color} is undefined. + *

    + * @apiNote It is recommended to avoid calling this method on + * the AWT Event Dispatch Thread since screen capture may be a lengthy + * operation, particularly if acquiring permissions is needed and involves + * user interaction. + * * @param x X position of pixel * @param y Y position of pixel + * @throws SecurityException if {@code readDisplayPixels} permission + * is not granted, or access to the screen is denied + * by the desktop environment * @return Color of the pixel */ public synchronized Color getPixelColor(int x, int y) { @@ -386,12 +442,25 @@ public synchronized Color getPixelColor(int x, int y) { } /** - * Creates an image containing pixels read from the screen. This image does - * not include the mouse cursor. + * Creates an image containing pixels read from the screen. + *

    + * If the desktop environment requires that permissions be granted + * to capture screen content, and the required permissions are not granted, + * then a {@code SecurityException} may be thrown, + * or the contents of the returned {@code BufferedImage} are undefined. + *

    + * @apiNote It is recommended to avoid calling this method on + * the AWT Event Dispatch Thread since screen capture may be a lengthy + * operation, particularly if acquiring permissions is needed and involves + * user interaction. + * * @param screenRect Rect to capture in screen coordinates * @return The captured image - * @throws IllegalArgumentException if {@code screenRect} width and height are not greater than zero - * @throws SecurityException if {@code readDisplayPixels} permission is not granted + * @throws IllegalArgumentException if {@code screenRect} width and height + * are not greater than zero + * @throws SecurityException if {@code readDisplayPixels} permission + * is not granted, or access to the screen is denied + * by the desktop environment * @see SecurityManager#checkPermission * @see AWTPermission */ @@ -401,7 +470,6 @@ public synchronized BufferedImage createScreenCapture(Rectangle screenRect) { /** * Creates an image containing pixels read from the screen. - * This image does not include the mouse cursor. * This method can be used in case there is a scaling transform * from user space to screen (device) space. * Typically this means that the display is a high resolution screen, @@ -434,8 +502,11 @@ public synchronized BufferedImage createScreenCapture(Rectangle screenRect) { * } * @param screenRect Rect to capture in screen coordinates * @return The captured image - * @throws IllegalArgumentException if {@code screenRect} width and height are not greater than zero - * @throws SecurityException if {@code readDisplayPixels} permission is not granted + * @throws IllegalArgumentException if {@code screenRect} width and height + * are not greater than zero + * @throws SecurityException if {@code readDisplayPixels} permission + * is not granted, or access to the screen is denied + * by the desktop environment * @see SecurityManager#checkPermission * @see AWTPermission * diff --git a/src/java.desktop/share/classes/javax/swing/JEditorPane.java b/src/java.desktop/share/classes/javax/swing/JEditorPane.java index fa019e39834..31fab42a402 100644 --- a/src/java.desktop/share/classes/javax/swing/JEditorPane.java +++ b/src/java.desktop/share/classes/javax/swing/JEditorPane.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024, 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 @@ -562,35 +562,37 @@ void read(InputStream in, Document doc) throws IOException { String charset = (String) getClientProperty("charset"); try(Reader r = (charset != null) ? new InputStreamReader(in, charset) : new InputStreamReader(in)) { - kit.read(r, doc, 0); - } catch (BadLocationException e) { - throw new IOException(e.getMessage()); - } catch (ChangedCharSetException changedCharSetException) { - String charSetSpec = changedCharSetException.getCharSetSpec(); - if (changedCharSetException.keyEqualsCharSet()) { - putClientProperty("charset", charSetSpec); - } else { - setCharsetFromContentTypeParameters(charSetSpec); - } try { - in.reset(); - } catch (IOException exception) { - //mark was invalidated - in.close(); - URL url = (URL)doc.getProperty(Document.StreamDescriptionProperty); - if (url != null) { - URLConnection conn = url.openConnection(); - in = conn.getInputStream(); + kit.read(r, doc, 0); + } catch (BadLocationException e) { + throw new IOException(e.getMessage()); + } catch (ChangedCharSetException changedCharSetException) { + String charSetSpec = changedCharSetException.getCharSetSpec(); + if (changedCharSetException.keyEqualsCharSet()) { + putClientProperty("charset", charSetSpec); } else { - //there is nothing we can do to recover stream - throw changedCharSetException; + setCharsetFromContentTypeParameters(charSetSpec); } + try { + in.reset(); + } catch (IOException exception) { + //mark was invalidated + in.close(); + URL url = (URL)doc.getProperty(Document.StreamDescriptionProperty); + if (url != null) { + URLConnection conn = url.openConnection(); + in = conn.getInputStream(); + } else { + //there is nothing we can do to recover stream + throw changedCharSetException; + } + } + try { + doc.remove(0, doc.getLength()); + } catch (BadLocationException e) {} + doc.putProperty("IgnoreCharsetDirective", Boolean.valueOf(true)); + read(in, doc); } - try { - doc.remove(0, doc.getLength()); - } catch (BadLocationException e) {} - doc.putProperty("IgnoreCharsetDirective", Boolean.valueOf(true)); - read(in, doc); } } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java index 462998a3e86..5e252b8102b 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -98,10 +98,13 @@ public void propertyChange(PropertyChangeEvent e) { * This method is used to interrupt file loading thread. */ public void invalidateFileCache() { - if (filesLoader != null) { - filesLoader.loadThread.interrupt(); - filesLoader.cancelRunnables(); - filesLoader = null; + synchronized (this) { + if (filesLoader != null) { + filesLoader.loadThread.interrupt(); + filesLoader = null; + // Increment fetch ID to invalidate pending DoChangeContents + fetchID.incrementAndGet(); + } } } @@ -156,14 +159,15 @@ public void validateFileCache() { if (currentDirectory == null) { return; } - if (filesLoader != null) { - filesLoader.loadThread.interrupt(); - filesLoader.cancelRunnables(); - } + synchronized (this) { + if (filesLoader != null) { + filesLoader.loadThread.interrupt(); + } - int fid = fetchID.incrementAndGet(); - setBusy(true, fid); - filesLoader = new FilesLoader(currentDirectory, fid); + int fid = fetchID.incrementAndGet(); + setBusy(true, fid); + filesLoader = new FilesLoader(currentDirectory, fid); + } } /** @@ -270,7 +274,6 @@ private final class FilesLoader implements Runnable { private final boolean fileSelectionEnabled; private final int fid; private final File currentDirectory; - private volatile DoChangeContents runnable; private final Thread loadThread; private FilesLoader(File currentDirectory, int fid) { @@ -291,22 +294,20 @@ public void run() { } private void run0() { - FileSystemView fileSystem = fileSystemView; - if (loadThread.isInterrupted()) { return; } - File[] list = fileSystem.getFiles(currentDirectory, useFileHiding); + File[] list = fileSystemView.getFiles(currentDirectory, useFileHiding); if (loadThread.isInterrupted()) { return; } final Vector newFileCache = new Vector(); - Vector newFiles = new Vector(); + final Vector newFiles = new Vector(); - // run through the file list, add directories and selectable files to fileCache + // Run through the file list, add directories and selectable files to fileCache // Note that this block must be OUTSIDE of Invoker thread because of // deadlock possibility with custom synchronized FileSystemView for (File file : list) { @@ -333,60 +334,68 @@ private void run0() { // To avoid loads of synchronizations with Invoker and improve performance we // execute the whole block on the COM thread - runnable = ShellFolder.invoke(new Callable() { + DoChangeContents runnable = ShellFolder.invoke(new Callable() { public DoChangeContents call() { - int newSize = newFileCache.size(); - int oldSize = fileCache.size(); - - if (newSize > oldSize) { - //see if interval is added - int start = oldSize; - int end = newSize; - for (int i = 0; i < oldSize; i++) { - if (!newFileCache.get(i).equals(fileCache.get(i))) { - start = i; - for (int j = i; j < newSize; j++) { - if (newFileCache.get(j).equals(fileCache.get(i))) { - end = j; - break; + synchronized (fileCache) { + int newSize = newFileCache.size(); + int oldSize = fileCache.size(); + + if (newSize > oldSize) { + //see if interval is added + int start = oldSize; + int end = newSize; + for (int i = 0; i < oldSize; i++) { + if (!newFileCache.get(i).equals(fileCache.get(i))) { + start = i; + for (int j = i; j < newSize; j++) { + if (newFileCache.get(j).equals(fileCache.get(i))) { + end = j; + break; + } } + break; } - break; } - } - if (start >= 0 && end > start - && newFileCache.subList(end, newSize).equals(fileCache.subList(start, oldSize))) { - if (loadThread.isInterrupted()) { - return null; + + if (start >= 0 && end > start + && newFileCache.subList(end, newSize) + .equals(fileCache.subList(start, oldSize))) { + if (loadThread.isInterrupted()) { + return null; + } + return new DoChangeContents(newFileCache.subList(start, end), + start, null, 0, fid); } - return new DoChangeContents(newFileCache.subList(start, end), start, null, 0, fid); - } - } else if (newSize < oldSize) { - //see if interval is removed - int start = -1; - int end = -1; - for (int i = 0; i < newSize; i++) { - if (!newFileCache.get(i).equals(fileCache.get(i))) { - start = i; - end = i + oldSize - newSize; - break; + } else if (newSize < oldSize) { + //see if interval is removed + int start = -1; + int end = -1; + for (int i = 0; i < newSize; i++) { + if (!newFileCache.get(i).equals(fileCache.get(i))) { + start = i; + end = i + oldSize - newSize; + break; + } + } + + if (start >= 0 && end > start + && fileCache.subList(end, oldSize) + .equals(newFileCache.subList(start, newSize))) { + if (loadThread.isInterrupted()) { + return null; + } + return new DoChangeContents(null, 0, + new Vector<>(fileCache.subList(start, end)), start, fid); } } - if (start >= 0 && end > start - && fileCache.subList(end, oldSize).equals(newFileCache.subList(start, newSize))) { + if (!fileCache.equals(newFileCache)) { if (loadThread.isInterrupted()) { return null; } - return new DoChangeContents(null, 0, new Vector<>(fileCache.subList(start, end)), start, fid); + return new DoChangeContents(newFileCache, 0, fileCache, 0, fid); } + return null; } - if (!fileCache.equals(newFileCache)) { - if (loadThread.isInterrupted()) { - cancelRunnables(); - } - return new DoChangeContents(newFileCache, 0, fileCache, 0, fid); - } - return null; } }); @@ -394,12 +403,6 @@ public DoChangeContents call() { SwingUtilities.invokeLater(runnable); } } - - private void cancelRunnables() { - if (runnable != null) { - runnable.cancel(); - } - } } @@ -508,13 +511,13 @@ public void run() { private final class DoChangeContents implements Runnable { private final List addFiles; private final List remFiles; - private boolean doFire = true; private final int fid; - private int addStart = 0; - private int remStart = 0; + private final int addStart; + private final int remStart; - DoChangeContents(List addFiles, int addStart, List remFiles, - int remStart, int fid) { + private DoChangeContents(List addFiles, int addStart, + List remFiles, int remStart, + int fid) { this.addFiles = addFiles; this.addStart = addStart; this.remFiles = remFiles; @@ -522,31 +525,32 @@ private final class DoChangeContents implements Runnable { this.fid = fid; } - synchronized void cancel() { - doFire = false; - } + @Override + public void run() { + if (fetchID.get() != fid) { + return; + } - public synchronized void run() { - if (fetchID.get() == fid && doFire) { - int remSize = (remFiles == null) ? 0 : remFiles.size(); - int addSize = (addFiles == null) ? 0 : addFiles.size(); - synchronized(fileCache) { - if (remSize > 0) { - fileCache.removeAll(remFiles); - } - if (addSize > 0) { - fileCache.addAll(addStart, addFiles); - } - files = null; - directories = null; + final int remSize = (remFiles == null) ? 0 : remFiles.size(); + final int addSize = (addFiles == null) ? 0 : addFiles.size(); + final int cacheSize; + synchronized (fileCache) { + if (remSize > 0) { + fileCache.removeAll(remFiles); } - if (remSize > 0 && addSize == 0) { - fireIntervalRemoved(BasicDirectoryModel.this, remStart, remStart + remSize - 1); - } else if (addSize > 0 && remSize == 0 && addStart + addSize <= fileCache.size()) { - fireIntervalAdded(BasicDirectoryModel.this, addStart, addStart + addSize - 1); - } else { - fireContentsChanged(); + if (addSize > 0) { + fileCache.addAll(addStart, addFiles); } + files = null; + directories = null; + cacheSize = fileCache.size(); + } + if (remSize > 0 && addSize == 0) { + fireIntervalRemoved(BasicDirectoryModel.this, remStart, remStart + remSize - 1); + } else if (addSize > 0 && remSize == 0 && addStart + addSize <= cacheSize) { + fireIntervalAdded(BasicDirectoryModel.this, addStart, addStart + addSize - 1); + } else { + fireContentsChanged(); } } } diff --git a/src/java.desktop/share/classes/sun/awt/SunToolkit.java b/src/java.desktop/share/classes/sun/awt/SunToolkit.java index be097df64bd..f8a3aee7bd2 100644 --- a/src/java.desktop/share/classes/sun/awt/SunToolkit.java +++ b/src/java.desktop/share/classes/sun/awt/SunToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -200,7 +200,7 @@ public abstract KeyboardFocusManagerPeer getKeyboardFocusManagerPeer() * access to Xlib, OpenGL, etc. However, these methods are implemented * in SunToolkit so that they can be called from shared code (e.g. * from the OGL pipeline) or from the X11 pipeline regardless of whether - * XToolkit or MToolkit is currently in use. There are native macros + * XToolkit is currently in use. There are native macros * (such as AWT_LOCK) defined in awt.h, so if the implementation of these * methods is changed, make sure it is compatible with the native macros. * diff --git a/src/java.desktop/share/legal/giflib.md b/src/java.desktop/share/legal/giflib.md index 0be4fb8226e..8b8fde8706d 100644 --- a/src/java.desktop/share/legal/giflib.md +++ b/src/java.desktop/share/legal/giflib.md @@ -1,4 +1,4 @@ -## GIFLIB v5.2.1 +## GIFLIB v5.2.2 ### GIFLIB License ``` @@ -24,7 +24,27 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -https://sourceforge.net/p/giflib/code/ci/master/tree/openbsd-reallocarray.c +tree/README -Copyright (c) 2008 Otto Moerbeek +== Authors == + +Gershon Elber +original giflib code + +Toshio Kuratomi +uncompressed gif writing code +former maintainer + +Eric Raymond +current as well as long time former maintainer of giflib code + +There have been many other contributors; see the attributions in the +version-control history to learn more. + + +tree/openbsd-reallocarray.c + +Copyright (C) 2008 Otto Moerbeek SPDX-License-Identifier: MIT + +``` diff --git a/src/java.desktop/share/legal/libpng.md b/src/java.desktop/share/legal/libpng.md index f420ccd94ed..cbffed81332 100644 --- a/src/java.desktop/share/legal/libpng.md +++ b/src/java.desktop/share/legal/libpng.md @@ -1,4 +1,4 @@ -## libpng v1.6.40 +## libpng v1.6.43 ### libpng License
    @@ -9,11 +9,11 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
     PNG Reference Library License version 2
     ---------------------------------------
     
    -Copyright (c) 1995-2023 The PNG Reference Library Authors.
    -Copyright (c) 2018-2023 Cosmin Truta
    -Copyright (c) 1998-2018 Glenn Randers-Pehrson
    -Copyright (c) 1996-1997 Andreas Dilger
    -Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    +Copyright (C) 1995-2024 The PNG Reference Library Authors.
    +Copyright (C) 2018-2024 Cosmin Truta
    +Copyright (C) 1998-2018 Glenn Randers-Pehrson
    +Copyright (C) 1996-1997 Andreas Dilger
    +Copyright (C) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
     
     The software is supplied "as is", without warranty of any kind,
     express or implied, including, without limitation, the warranties
    @@ -157,7 +157,9 @@ PNG REFERENCE LIBRARY AUTHORS
     This is the list of PNG Reference Library ("libpng") Contributing
     Authors, for copyright and licensing purposes.
     
    + * Adam Richter
      * Andreas Dilger
    + * Chris Blume
      * Cosmin Truta
      * Dave Martindale
      * Eric S. Raymond
    @@ -186,21 +188,28 @@ Authors, for copyright and licensing purposes.
      * Vadim Barkov
      * Willem van Schaik
      * Zhijie Liang
    + * Apple Inc.
    +    - Zixu Wang (王子旭)
      * Arm Holdings
    -   - Richard Townsend
    +    - Richard Townsend
      * Google Inc.
    -   - Dan Field
    -   - Leon Scroggins III
    -   - Matt Sarett
    -   - Mike Klein
    -   - Sami Boukortt
    -   - Wan-Teh Chang
    +    - Dan Field
    +    - Leon Scroggins III
    +    - Matt Sarett
    +    - Mike Klein
    +    - Sami Boukortt
    +    - Wan-Teh Chang
    + * Loongson Technology Corporation Ltd.
    +    - GuXiWei (顾希伟)
    +    - JinBo (金波)
    +    - ZhangLixia (张利霞)
     
     The build projects, the build scripts, the test scripts, and other
    -files in the "ci", "projects", "scripts" and "tests" directories, have
    +files in the "projects", "scripts" and "tests" directories, have
     other copyright owners, but are released under the libpng license.
     
    -Some files in the "contrib" directory, and some tools-generated files
    -that are distributed with libpng, have other copyright owners, and are
    -released under other open source licenses.
    +Some files in the "ci" and "contrib" directories, as well as some
    +of the tools-generated files that are distributed with libpng, have
    +other copyright owners, and are released under other open source
    +licenses.
     ```
    diff --git a/src/java.desktop/share/native/liblcms/cmsio0.c b/src/java.desktop/share/native/liblcms/cmsio0.c
    index 1b32f9f4159..05baa9392e2 100644
    --- a/src/java.desktop/share/native/liblcms/cmsio0.c
    +++ b/src/java.desktop/share/native/liblcms/cmsio0.c
    @@ -1660,7 +1660,7 @@ cmsBool IsTypeSupported(cmsTagDescriptor* TagDescriptor, cmsTagTypeSignature Typ
     void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
     {
         _cmsICCPROFILE* Icc = (_cmsICCPROFILE*) hProfile;
    -    cmsIOHANDLER* io = Icc ->IOhandler;
    +    cmsIOHANDLER* io;
         cmsTagTypeHandler* TypeHandler;
         cmsTagTypeHandler LocalTypeHandler;
         cmsTagDescriptor*  TagDescriptor;
    @@ -1705,6 +1705,8 @@ void* CMSEXPORT cmsReadTag(cmsHPROFILE hProfile, cmsTagSignature sig)
     
         if (TagSize < 8) goto Error;
     
    +    io = Icc ->IOhandler;
    +
         if (io == NULL) { // This is a built-in profile that has been manipulated, abort early
     
             cmsSignalError(Icc->ContextID, cmsERROR_CORRUPTION_DETECTED, "Corrupted built-in profile.");
    diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c b/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c
    index 6ddfb46060d..0b2860b4b50 100644
    --- a/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c
    +++ b/src/java.desktop/share/native/libsplashscreen/giflib/dgif_lib.c
    @@ -34,11 +34,11 @@ SPDX-License-Identifier: MIT
     
     *****************************************************************************/
     
    -#include 
    +#include 
     #include 
     #include 
    -#include 
     #include 
    +#include 
     #include 
     
     #ifdef _WIN32
    @@ -55,18 +55,19 @@ SPDX-License-Identifier: MIT
     
     /* avoid extra function call in case we use fread (TVT) */
     static int InternalRead(GifFileType *gif, GifByteType *buf, int len) {
    -    //fprintf(stderr, "### Read: %d\n", len);
    -    return
    -    (((GifFilePrivateType*)gif->Private)->Read ?
    -     ((GifFilePrivateType*)gif->Private)->Read(gif,buf,len) :
    -     fread(buf,1,len,((GifFilePrivateType*)gif->Private)->File));
    +    // fprintf(stderr, "### Read: %d\n", len);
    +    return (((GifFilePrivateType *)gif->Private)->Read
    +                ? ((GifFilePrivateType *)gif->Private)->Read(gif, buf, len)
    +                : fread(buf, 1, len,
    +                        ((GifFilePrivateType *)gif->Private)->File));
     }
     
     static int DGifGetWord(GifFileType *GifFile, GifWord *Word);
     static int DGifSetupDecompress(GifFileType *GifFile);
     static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
                                   int LineLen);
    -static int DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode);
    +static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code,
    +                             int ClearCode);
     static int DGifDecompressInput(GifFileType *GifFile, int *Code);
     static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
                                  GifByteType *NextByte);
    @@ -76,15 +77,14 @@ static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
      Returns dynamically allocated GifFileType pointer which serves as the GIF
      info record.
     ******************************************************************************/
    -GifFileType *
    -DGifOpenFileName(const char *FileName, int *Error)
    -{
    +GifFileType *DGifOpenFileName(const char *FileName, int *Error) {
         int FileHandle;
         GifFileType *GifFile;
     
         if ((FileHandle = open(FileName, O_RDONLY)) == -1) {
    -        if (Error != NULL)
    +        if (Error != NULL) {
                 *Error = D_GIF_ERR_OPEN_FAILED;
    +        }
             return NULL;
         }
     
    @@ -97,9 +97,7 @@ DGifOpenFileName(const char *FileName, int *Error)
      Returns dynamically allocated GifFileType pointer which serves as the GIF
      info record.
     ******************************************************************************/
    -GifFileType *
    -DGifOpenFileHandle(int FileHandle, int *Error)
    -{
    +GifFileType *DGifOpenFileHandle(int FileHandle, int *Error) {
         char Buf[GIF_STAMP_LEN + 1];
         GifFileType *GifFile;
         GifFilePrivateType *Private;
    @@ -107,13 +105,14 @@ DGifOpenFileHandle(int FileHandle, int *Error)
     
         GifFile = (GifFileType *)malloc(sizeof(GifFileType));
         if (GifFile == NULL) {
    -        if (Error != NULL)
    +        if (Error != NULL) {
                 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
    +        }
             (void)close(FileHandle);
             return NULL;
         }
     
    -    /*@i1@*/memset(GifFile, '\0', sizeof(GifFileType));
    +    /*@i1@*/ memset(GifFile, '\0', sizeof(GifFileType));
     
         /* Belt and suspenders, in case the null pointer isn't zero */
         GifFile->SavedImages = NULL;
    @@ -121,35 +120,38 @@ DGifOpenFileHandle(int FileHandle, int *Error)
     
         Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
         if (Private == NULL) {
    -        if (Error != NULL)
    +        if (Error != NULL) {
                 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
    +        }
             (void)close(FileHandle);
             free((char *)GifFile);
             return NULL;
         }
     
    -    /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
    +    /*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType));
     
     #ifdef _WIN32
    -    _setmode(FileHandle, O_BINARY);    /* Make sure it is in binary mode. */
    -#endif /* _WIN32 */
    +    _setmode(FileHandle, O_BINARY); /* Make sure it is in binary mode. */
    +#endif                                  /* _WIN32 */
     
    -    f = fdopen(FileHandle, "rb");    /* Make it into a stream: */
    +    f = fdopen(FileHandle, "rb"); /* Make it into a stream: */
     
         /*@-mustfreeonly@*/
         GifFile->Private = (void *)Private;
         Private->FileHandle = FileHandle;
         Private->File = f;
         Private->FileState = FILE_STATE_READ;
    -    Private->Read = NULL;        /* don't use alternate input method (TVT) */
    -    GifFile->UserData = NULL;    /* TVT */
    +    Private->Read = NULL;     /* don't use alternate input method (TVT) */
    +    GifFile->UserData = NULL; /* TVT */
         /*@=mustfreeonly@*/
     
         /* Let's see if this is a GIF file: */
         /* coverity[check_return] */
    -    if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
    -        if (Error != NULL)
    +    if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) !=
    +        GIF_STAMP_LEN) {
    +        if (Error != NULL) {
                 *Error = D_GIF_ERR_READ_FAILED;
    +        }
             (void)fclose(f);
             free((char *)Private);
             free((char *)GifFile);
    @@ -159,8 +161,9 @@ DGifOpenFileHandle(int FileHandle, int *Error)
         /* Check for GIF prefix at start of file */
         Buf[GIF_STAMP_LEN] = 0;
         if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
    -        if (Error != NULL)
    +        if (Error != NULL) {
                 *Error = D_GIF_ERR_NOT_GIF_FILE;
    +        }
             (void)fclose(f);
             free((char *)Private);
             free((char *)GifFile);
    @@ -177,7 +180,7 @@ DGifOpenFileHandle(int FileHandle, int *Error)
         GifFile->Error = 0;
     
         /* What version of GIF? */
    -    Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
    +    Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9');
     
         return GifFile;
     }
    @@ -185,17 +188,16 @@ DGifOpenFileHandle(int FileHandle, int *Error)
     /******************************************************************************
      GifFileType constructor with user supplied input function (TVT)
     ******************************************************************************/
    -GifFileType *
    -DGifOpen(void *userData, InputFunc readFunc, int *Error)
    -{
    +GifFileType *DGifOpen(void *userData, InputFunc readFunc, int *Error) {
         char Buf[GIF_STAMP_LEN + 1];
         GifFileType *GifFile;
         GifFilePrivateType *Private;
     
         GifFile = (GifFileType *)malloc(sizeof(GifFileType));
         if (GifFile == NULL) {
    -        if (Error != NULL)
    +        if (Error != NULL) {
                 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
    +        }
             return NULL;
         }
     
    @@ -207,26 +209,29 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error)
     
         Private = (GifFilePrivateType *)calloc(1, sizeof(GifFilePrivateType));
         if (!Private) {
    -        if (Error != NULL)
    +        if (Error != NULL) {
                 *Error = D_GIF_ERR_NOT_ENOUGH_MEM;
    +        }
             free((char *)GifFile);
             return NULL;
         }
    -    /*@i1@*/memset(Private, '\0', sizeof(GifFilePrivateType));
    +    /*@i1@*/ memset(Private, '\0', sizeof(GifFilePrivateType));
     
         GifFile->Private = (void *)Private;
         Private->FileHandle = 0;
         Private->File = NULL;
         Private->FileState = FILE_STATE_READ;
     
    -    Private->Read = readFunc;    /* TVT */
    -    GifFile->UserData = userData;    /* TVT */
    +    Private->Read = readFunc;     /* TVT */
    +    GifFile->UserData = userData; /* TVT */
     
         /* Lets see if this is a GIF file: */
         /* coverity[check_return] */
    -    if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) != GIF_STAMP_LEN) {
    -        if (Error != NULL)
    +    if (InternalRead(GifFile, (unsigned char *)Buf, GIF_STAMP_LEN) !=
    +        GIF_STAMP_LEN) {
    +        if (Error != NULL) {
                 *Error = D_GIF_ERR_READ_FAILED;
    +        }
             free((char *)Private);
             free((char *)GifFile);
             return NULL;
    @@ -235,8 +240,9 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error)
         /* Check for GIF prefix at start of file */
         Buf[GIF_STAMP_LEN] = '\0';
         if (strncmp(GIF_STAMP, Buf, GIF_VERSION_POS) != 0) {
    -        if (Error != NULL)
    +        if (Error != NULL) {
                 *Error = D_GIF_ERR_NOT_GIF_FILE;
    +        }
             free((char *)Private);
             free((char *)GifFile);
             return NULL;
    @@ -245,15 +251,16 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error)
         if (DGifGetScreenDesc(GifFile) == GIF_ERROR) {
             free((char *)Private);
             free((char *)GifFile);
    -        if (Error != NULL)
    +        if (Error != NULL) {
                 *Error = D_GIF_ERR_NO_SCRN_DSCR;
    +        }
             return NULL;
         }
     
         GifFile->Error = 0;
     
         /* What version of GIF? */
    -    Private->gif89 = (Buf[GIF_VERSION_POS] == '9');
    +    Private->gif89 = (Buf[GIF_VERSION_POS + 1] == '9');
     
         return GifFile;
     }
    @@ -262,9 +269,7 @@ DGifOpen(void *userData, InputFunc readFunc, int *Error)
      This routine should be called before any other DGif calls. Note that
      this routine is called automatically from DGif file open routines.
     ******************************************************************************/
    -int
    -DGifGetScreenDesc(GifFileType *GifFile)
    -{
    +int DGifGetScreenDesc(GifFileType *GifFile) {
         int BitsPerPixel;
         bool SortFlag;
         GifByteType Buf[3];
    @@ -278,8 +283,9 @@ DGifGetScreenDesc(GifFileType *GifFile)
     
         /* Put the screen descriptor into the file: */
         if (DGifGetWord(GifFile, &GifFile->SWidth) == GIF_ERROR ||
    -        DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR)
    +        DGifGetWord(GifFile, &GifFile->SHeight) == GIF_ERROR) {
             return GIF_ERROR;
    +    }
     
         if (InternalRead(GifFile, Buf, 3) != 3) {
             GifFile->Error = D_GIF_ERR_READ_FAILED;
    @@ -292,7 +298,7 @@ DGifGetScreenDesc(GifFileType *GifFile)
         BitsPerPixel = (Buf[0] & 0x07) + 1;
         GifFile->SBackGroundColor = Buf[1];
         GifFile->AspectByte = Buf[2];
    -    if (Buf[0] & 0x80) {    /* Do we have global color map? */
    +    if (Buf[0] & 0x80) { /* Do we have global color map? */
             int i;
     
             GifFile->SColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
    @@ -327,23 +333,20 @@ DGifGetScreenDesc(GifFileType *GifFile)
         return GIF_OK;
     }
     
    -const char *
    -DGifGetGifVersion(GifFileType *GifFile)
    -{
    -    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
    +const char *DGifGetGifVersion(GifFileType *GifFile) {
    +    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
    -    if (Private->gif89)
    +    if (Private->gif89) {
             return GIF89_STAMP;
    -    else
    +    } else {
             return GIF87_STAMP;
    +    }
     }
     
     /******************************************************************************
      This routine should be called before any attempt to read an image.
     ******************************************************************************/
    -int
    -DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type)
    -{
    +int DGifGetRecordType(GifFileType *GifFile, GifRecordType *Type) {
         GifByteType Buf;
         GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
    @@ -359,29 +362,27 @@ DGifGetRecordType(GifFileType *GifFile, GifRecordType* Type)
             return GIF_ERROR;
         }
     
    -    //fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf);
    +    // fprintf(stderr, "### DGifGetRecordType: %02x\n", Buf);
         switch (Buf) {
    -      case DESCRIPTOR_INTRODUCER:
    -          *Type = IMAGE_DESC_RECORD_TYPE;
    -          break;
    -      case EXTENSION_INTRODUCER:
    -          *Type = EXTENSION_RECORD_TYPE;
    -          break;
    -      case TERMINATOR_INTRODUCER:
    -          *Type = TERMINATE_RECORD_TYPE;
    -          break;
    -      default:
    -          *Type = UNDEFINED_RECORD_TYPE;
    -          GifFile->Error = D_GIF_ERR_WRONG_RECORD;
    -          return GIF_ERROR;
    +    case DESCRIPTOR_INTRODUCER:
    +        *Type = IMAGE_DESC_RECORD_TYPE;
    +        break;
    +    case EXTENSION_INTRODUCER:
    +        *Type = EXTENSION_RECORD_TYPE;
    +        break;
    +    case TERMINATOR_INTRODUCER:
    +        *Type = TERMINATE_RECORD_TYPE;
    +        break;
    +    default:
    +        *Type = UNDEFINED_RECORD_TYPE;
    +        GifFile->Error = D_GIF_ERR_WRONG_RECORD;
    +        return GIF_ERROR;
         }
     
         return GIF_OK;
     }
     
    -int
    -DGifGetImageHeader(GifFileType *GifFile)
    -{
    +int DGifGetImageHeader(GifFileType *GifFile) {
         unsigned int BitsPerPixel;
         GifByteType Buf[3];
         GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
    @@ -395,8 +396,9 @@ DGifGetImageHeader(GifFileType *GifFile)
         if (DGifGetWord(GifFile, &GifFile->Image.Left) == GIF_ERROR ||
             DGifGetWord(GifFile, &GifFile->Image.Top) == GIF_ERROR ||
             DGifGetWord(GifFile, &GifFile->Image.Width) == GIF_ERROR ||
    -        DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR)
    +        DGifGetWord(GifFile, &GifFile->Image.Height) == GIF_ERROR) {
             return GIF_ERROR;
    +    }
         if (InternalRead(GifFile, Buf, 1) != 1) {
             GifFile->Error = D_GIF_ERR_READ_FAILED;
             GifFreeMapObject(GifFile->Image.ColorMap);
    @@ -415,7 +417,8 @@ DGifGetImageHeader(GifFileType *GifFile)
         if (Buf[0] & 0x80) {
             unsigned int i;
     
    -        GifFile->Image.ColorMap = GifMakeMapObject(1 << BitsPerPixel, NULL);
    +        GifFile->Image.ColorMap =
    +            GifMakeMapObject(1 << BitsPerPixel, NULL);
             if (GifFile->Image.ColorMap == NULL) {
                 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
                 return GIF_ERROR;
    @@ -436,8 +439,8 @@ DGifGetImageHeader(GifFileType *GifFile)
             }
         }
     
    -    Private->PixelCount = (long)GifFile->Image.Width *
    -       (long)GifFile->Image.Height;
    +    Private->PixelCount =
    +        (long)GifFile->Image.Width * (long)GifFile->Image.Height;
     
         /* Reset decompress algorithm parameters. */
         return DGifSetupDecompress(GifFile);
    @@ -447,9 +450,7 @@ DGifGetImageHeader(GifFileType *GifFile)
      This routine should be called before any attempt to read an image.
      Note it is assumed the Image desc. header has been read.
     ******************************************************************************/
    -int
    -DGifGetImageDesc(GifFileType *GifFile)
    -{
    +int DGifGetImageDesc(GifFileType *GifFile) {
         GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
         SavedImage *sp;
     
    @@ -464,9 +465,9 @@ DGifGetImageDesc(GifFileType *GifFile)
         }
     
         if (GifFile->SavedImages) {
    -        SavedImage* new_saved_images =
    -            (SavedImage *)reallocarray(GifFile->SavedImages,
    -                            (GifFile->ImageCount + 1), sizeof(SavedImage));
    +        SavedImage *new_saved_images = (SavedImage *)reallocarray(
    +            GifFile->SavedImages, (GifFile->ImageCount + 1),
    +            sizeof(SavedImage));
             if (new_saved_images == NULL) {
                 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
                 return GIF_ERROR;
    @@ -474,7 +475,7 @@ DGifGetImageDesc(GifFileType *GifFile)
             GifFile->SavedImages = new_saved_images;
         } else {
             if ((GifFile->SavedImages =
    -             (SavedImage *) malloc(sizeof(SavedImage))) == NULL) {
    +                 (SavedImage *)malloc(sizeof(SavedImage))) == NULL) {
                 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
                 return GIF_ERROR;
             }
    @@ -483,9 +484,9 @@ DGifGetImageDesc(GifFileType *GifFile)
         sp = &GifFile->SavedImages[GifFile->ImageCount];
         memcpy(&sp->ImageDesc, &GifFile->Image, sizeof(GifImageDesc));
         if (GifFile->Image.ColorMap != NULL) {
    -        sp->ImageDesc.ColorMap = GifMakeMapObject(
    -                                 GifFile->Image.ColorMap->ColorCount,
    -                                 GifFile->Image.ColorMap->Colors);
    +        sp->ImageDesc.ColorMap =
    +            GifMakeMapObject(GifFile->Image.ColorMap->ColorCount,
    +                             GifFile->Image.ColorMap->Colors);
             if (sp->ImageDesc.ColorMap == NULL) {
                 GifFile->Error = D_GIF_ERR_NOT_ENOUGH_MEM;
                 return GIF_ERROR;
    @@ -493,7 +494,7 @@ DGifGetImageDesc(GifFileType *GifFile)
         }
         sp->RasterBits = (unsigned char *)NULL;
         sp->ExtensionBlockCount = 0;
    -    sp->ExtensionBlocks = (ExtensionBlock *) NULL;
    +    sp->ExtensionBlocks = (ExtensionBlock *)NULL;
     
         GifFile->ImageCount++;
     
    @@ -503,11 +504,9 @@ DGifGetImageDesc(GifFileType *GifFile)
     /******************************************************************************
      Get one full scanned line (Line) of length LineLen from GIF file.
     ******************************************************************************/
    -int
    -DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
    -{
    +int DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen) {
         GifByteType *Dummy;
    -    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
    +    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
         if (!IS_READABLE(Private)) {
             /* This file was NOT open for reading: */
    @@ -515,8 +514,9 @@ DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
             return GIF_ERROR;
         }
     
    -    if (!LineLen)
    +    if (!LineLen) {
             LineLen = GifFile->Image.Width;
    +    }
     
         if ((Private->PixelCount -= LineLen) > 0xffff0000UL) {
             GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
    @@ -525,56 +525,59 @@ DGifGetLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
     
         if (DGifDecompressLine(GifFile, Line, LineLen) == GIF_OK) {
             if (Private->PixelCount == 0) {
    -            /* We probably won't be called any more, so let's clean up
    -             * everything before we return: need to flush out all the
    -             * rest of image until an empty block (size 0)
    +            /* We probably won't be called any more, so let's clean
    +             * up everything before we return: need to flush out all
    +             * the rest of image until an empty block (size 0)
                  * detected. We use GetCodeNext.
                  */
    -            do
    -                if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
    +            do {
    +                if (DGifGetCodeNext(GifFile, &Dummy) ==
    +                    GIF_ERROR) {
                         return GIF_ERROR;
    -            while (Dummy != NULL) ;
    +                }
    +            } while (Dummy != NULL);
             }
             return GIF_OK;
    -    } else
    +    } else {
             return GIF_ERROR;
    +    }
     }
     
     /******************************************************************************
      Put one pixel (Pixel) into GIF file.
     ******************************************************************************/
    -int
    -DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
    -{
    +int DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel) {
         GifByteType *Dummy;
    -    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
    +    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
         if (!IS_READABLE(Private)) {
             /* This file was NOT open for reading: */
             GifFile->Error = D_GIF_ERR_NOT_READABLE;
             return GIF_ERROR;
         }
    -    if (--Private->PixelCount > 0xffff0000UL)
    -    {
    +    if (--Private->PixelCount > 0xffff0000UL) {
             GifFile->Error = D_GIF_ERR_DATA_TOO_BIG;
             return GIF_ERROR;
         }
     
         if (DGifDecompressLine(GifFile, &Pixel, 1) == GIF_OK) {
             if (Private->PixelCount == 0) {
    -            /* We probably won't be called any more, so let's clean up
    -             * everything before we return: need to flush out all the
    -             * rest of image until an empty block (size 0)
    +            /* We probably won't be called any more, so let's clean
    +             * up everything before we return: need to flush out all
    +             * the rest of image until an empty block (size 0)
                  * detected. We use GetCodeNext.
                  */
    -            do
    -                if (DGifGetCodeNext(GifFile, &Dummy) == GIF_ERROR)
    +            do {
    +                if (DGifGetCodeNext(GifFile, &Dummy) ==
    +                    GIF_ERROR) {
                         return GIF_ERROR;
    -            while (Dummy != NULL) ;
    +                }
    +            } while (Dummy != NULL);
             }
             return GIF_OK;
    -    } else
    +    } else {
             return GIF_ERROR;
    +    }
     }
     
     /******************************************************************************
    @@ -584,13 +587,12 @@ DGifGetPixel(GifFileType *GifFile, GifPixelType Pixel)
      The Extension should NOT be freed by the user (not dynamically allocated).
      Note it is assumed the Extension description header has been read.
     ******************************************************************************/
    -int
    -DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
    -{
    +int DGifGetExtension(GifFileType *GifFile, int *ExtCode,
    +                     GifByteType **Extension) {
         GifByteType Buf;
         GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
    -    //fprintf(stderr, "### -> DGifGetExtension:\n");
    +    // fprintf(stderr, "### -> DGifGetExtension:\n");
         if (!IS_READABLE(Private)) {
             /* This file was NOT open for reading: */
             GifFile->Error = D_GIF_ERR_NOT_READABLE;
    @@ -603,7 +605,8 @@ DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
             return GIF_ERROR;
         }
         *ExtCode = Buf;
    -    //fprintf(stderr, "### <- DGifGetExtension: %02x, about to call next\n", Buf);
    +    // fprintf(stderr, "### <- DGifGetExtension: %02x, about to call
    +    // next\n", Buf);
     
         return DGifGetExtensionNext(GifFile, Extension);
     }
    @@ -613,30 +616,30 @@ DGifGetExtension(GifFileType *GifFile, int *ExtCode, GifByteType **Extension)
      routine should be called until NULL Extension is returned.
      The Extension should NOT be freed by the user (not dynamically allocated).
     ******************************************************************************/
    -int
    -DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension)
    -{
    +int DGifGetExtensionNext(GifFileType *GifFile, GifByteType **Extension) {
         GifByteType Buf;
         GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
    -    //fprintf(stderr, "### -> DGifGetExtensionNext\n");
    +    // fprintf(stderr, "### -> DGifGetExtensionNext\n");
         if (InternalRead(GifFile, &Buf, 1) != 1) {
             GifFile->Error = D_GIF_ERR_READ_FAILED;
             return GIF_ERROR;
         }
    -    //fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf);
    +    // fprintf(stderr, "### DGifGetExtensionNext sees %d\n", Buf);
     
         if (Buf > 0) {
    -        *Extension = Private->Buf;    /* Use private unused buffer. */
    -        (*Extension)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
    -        /* coverity[tainted_data,check_return] */
    +        *Extension = Private->Buf; /* Use private unused buffer. */
    +        (*Extension)[0] =
    +            Buf; /* Pascal strings notation (pos. 0 is len.). */
    +                 /* coverity[tainted_data,check_return] */
             if (InternalRead(GifFile, &((*Extension)[1]), Buf) != Buf) {
                 GifFile->Error = D_GIF_ERR_READ_FAILED;
                 return GIF_ERROR;
             }
    -    } else
    +    } else {
             *Extension = NULL;
    -    //fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension);
    +    }
    +    // fprintf(stderr, "### <- DGifGetExtensionNext: %p\n", Extension);
     
         return GIF_OK;
     }
    @@ -647,19 +650,20 @@ DGifGetExtensionNext(GifFileType *GifFile, GifByteType ** Extension)
     
     int DGifExtensionToGCB(const size_t GifExtensionLength,
                            const GifByteType *GifExtension,
    -                       GraphicsControlBlock *GCB)
    -{
    +                       GraphicsControlBlock *GCB) {
         if (GifExtensionLength != 4) {
             return GIF_ERROR;
         }
     
         GCB->DisposalMode = (GifExtension[0] >> 2) & 0x07;
         GCB->UserInputFlag = (GifExtension[0] & 0x02) != 0;
    -    GCB->DelayTime = UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
    -    if (GifExtension[0] & 0x01)
    +    GCB->DelayTime =
    +        UNSIGNED_LITTLE_ENDIAN(GifExtension[1], GifExtension[2]);
    +    if (GifExtension[0] & 0x01) {
             GCB->TransparentColor = (int)GifExtension[3];
    -    else
    +    } else {
             GCB->TransparentColor = NO_TRANSPARENT_COLOR;
    +    }
     
         return GIF_OK;
     }
    @@ -668,23 +672,27 @@ int DGifExtensionToGCB(const size_t GifExtensionLength,
      Extract the Graphics Control Block for a saved image, if it exists.
     ******************************************************************************/
     
    -int DGifSavedExtensionToGCB(GifFileType *GifFile,
    -                int ImageIndex, GraphicsControlBlock *GCB)
    -{
    +int DGifSavedExtensionToGCB(GifFileType *GifFile, int ImageIndex,
    +                            GraphicsControlBlock *GCB) {
         int i;
     
    -    if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1)
    +    if (ImageIndex < 0 || ImageIndex > GifFile->ImageCount - 1) {
             return GIF_ERROR;
    +    }
     
         GCB->DisposalMode = DISPOSAL_UNSPECIFIED;
         GCB->UserInputFlag = false;
         GCB->DelayTime = 0;
         GCB->TransparentColor = NO_TRANSPARENT_COLOR;
     
    -    for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount; i++) {
    -        ExtensionBlock *ep = &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
    -        if (ep->Function == GRAPHICS_EXT_FUNC_CODE)
    -            return DGifExtensionToGCB(ep->ByteCount, ep->Bytes, GCB);
    +    for (i = 0; i < GifFile->SavedImages[ImageIndex].ExtensionBlockCount;
    +         i++) {
    +        ExtensionBlock *ep =
    +            &GifFile->SavedImages[ImageIndex].ExtensionBlocks[i];
    +        if (ep->Function == GRAPHICS_EXT_FUNC_CODE) {
    +            return DGifExtensionToGCB(ep->ByteCount, ep->Bytes,
    +                                      GCB);
    +        }
         }
     
         return GIF_ERROR;
    @@ -693,13 +701,12 @@ int DGifSavedExtensionToGCB(GifFileType *GifFile,
     /******************************************************************************
      This routine should be called last, to close the GIF file.
     ******************************************************************************/
    -int
    -DGifCloseFile(GifFileType *GifFile, int *ErrorCode)
    -{
    +int DGifCloseFile(GifFileType *GifFile, int *ErrorCode) {
         GifFilePrivateType *Private;
     
    -    if (GifFile == NULL || GifFile->Private == NULL)
    +    if (GifFile == NULL || GifFile->Private == NULL) {
             return GIF_ERROR;
    +    }
     
         if (GifFile->Image.ColorMap) {
             GifFreeMapObject(GifFile->Image.ColorMap);
    @@ -716,22 +723,25 @@ DGifCloseFile(GifFileType *GifFile, int *ErrorCode)
             GifFile->SavedImages = NULL;
         }
     
    -    GifFreeExtensions(&GifFile->ExtensionBlockCount, &GifFile->ExtensionBlocks);
    +    GifFreeExtensions(&GifFile->ExtensionBlockCount,
    +                      &GifFile->ExtensionBlocks);
     
    -    Private = (GifFilePrivateType *) GifFile->Private;
    +    Private = (GifFilePrivateType *)GifFile->Private;
     
         if (!IS_READABLE(Private)) {
             /* This file was NOT open for reading: */
    -        if (ErrorCode != NULL)
    +        if (ErrorCode != NULL) {
                 *ErrorCode = D_GIF_ERR_NOT_READABLE;
    +        }
             free((char *)GifFile->Private);
             free(GifFile);
             return GIF_ERROR;
         }
     
         if (Private->File && (fclose(Private->File) != 0)) {
    -        if (ErrorCode != NULL)
    +        if (ErrorCode != NULL) {
                 *ErrorCode = D_GIF_ERR_CLOSE_FAILED;
    +        }
             free((char *)GifFile->Private);
             free(GifFile);
             return GIF_ERROR;
    @@ -739,17 +749,16 @@ DGifCloseFile(GifFileType *GifFile, int *ErrorCode)
     
         free((char *)GifFile->Private);
         free(GifFile);
    -    if (ErrorCode != NULL)
    +    if (ErrorCode != NULL) {
             *ErrorCode = D_GIF_SUCCEEDED;
    +    }
         return GIF_OK;
     }
     
     /******************************************************************************
      Get 2 bytes (word) from the given file:
     ******************************************************************************/
    -static int
    -DGifGetWord(GifFileType *GifFile, GifWord *Word)
    -{
    +static int DGifGetWord(GifFileType *GifFile, GifWord *Word) {
         unsigned char c[2];
     
         /* coverity[check_return] */
    @@ -769,9 +778,7 @@ DGifGetWord(GifFileType *GifFile, GifWord *Word)
      to DGifGetCodeNext, until NULL block is returned.
      The block should NOT be freed by the user (not dynamically allocated).
     ******************************************************************************/
    -int
    -DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
    -{
    +int DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock) {
         GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
         if (!IS_READABLE(Private)) {
    @@ -790,9 +797,7 @@ DGifGetCode(GifFileType *GifFile, int *CodeSize, GifByteType **CodeBlock)
      called until NULL block is returned.
      The block should NOT be freed by the user (not dynamically allocated).
     ******************************************************************************/
    -int
    -DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
    -{
    +int DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock) {
         GifByteType Buf;
         GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
    @@ -805,17 +810,19 @@ DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
     
         /* coverity[lower_bounds] */
         if (Buf > 0) {
    -        *CodeBlock = Private->Buf;    /* Use private unused buffer. */
    -        (*CodeBlock)[0] = Buf;  /* Pascal strings notation (pos. 0 is len.). */
    -        /* coverity[tainted_data] */
    +        *CodeBlock = Private->Buf; /* Use private unused buffer. */
    +        (*CodeBlock)[0] =
    +            Buf; /* Pascal strings notation (pos. 0 is len.). */
    +                 /* coverity[tainted_data] */
             if (InternalRead(GifFile, &((*CodeBlock)[1]), Buf) != Buf) {
                 GifFile->Error = D_GIF_ERR_READ_FAILED;
                 return GIF_ERROR;
             }
         } else {
             *CodeBlock = NULL;
    -        Private->Buf[0] = 0;    /* Make sure the buffer is empty! */
    -        Private->PixelCount = 0;    /* And local info. indicate image read. */
    +        Private->Buf[0] = 0; /* Make sure the buffer is empty! */
    +        Private->PixelCount =
    +            0; /* And local info. indicate image read. */
         }
     
         return GIF_OK;
    @@ -824,41 +831,43 @@ DGifGetCodeNext(GifFileType *GifFile, GifByteType **CodeBlock)
     /******************************************************************************
      Setup the LZ decompression for this image:
     ******************************************************************************/
    -static int
    -DGifSetupDecompress(GifFileType *GifFile)
    -{
    +static int DGifSetupDecompress(GifFileType *GifFile) {
         int i, BitsPerPixel;
         GifByteType CodeSize;
         GifPrefixType *Prefix;
         GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
         /* coverity[check_return] */
    -    if (InternalRead(GifFile, &CodeSize, 1) < 1) {    /* Read Code size from file. */
    -        return GIF_ERROR;    /* Failed to read Code size. */
    +    if (InternalRead(GifFile, &CodeSize, 1) <
    +        1) { /* Read Code size from file. */
    +        GifFile->Error = D_GIF_ERR_READ_FAILED;
    +        return GIF_ERROR; /* Failed to read Code size. */
         }
         BitsPerPixel = CodeSize;
     
         /* this can only happen on a severely malformed GIF */
         if (BitsPerPixel > 8) {
    -        GifFile->Error = D_GIF_ERR_READ_FAILED;    /* somewhat bogus error code */
    -        return GIF_ERROR;    /* Failed to read Code size. */
    +        GifFile->Error =
    +            D_GIF_ERR_READ_FAILED; /* somewhat bogus error code */
    +        return GIF_ERROR;          /* Failed to read Code size. */
         }
     
    -    Private->Buf[0] = 0;    /* Input Buffer empty. */
    +    Private->Buf[0] = 0; /* Input Buffer empty. */
         Private->BitsPerPixel = BitsPerPixel;
         Private->ClearCode = (1 << BitsPerPixel);
         Private->EOFCode = Private->ClearCode + 1;
         Private->RunningCode = Private->EOFCode + 1;
    -    Private->RunningBits = BitsPerPixel + 1;    /* Number of bits per code. */
    -    Private->MaxCode1 = 1 << Private->RunningBits;    /* Max. code + 1. */
    -    Private->StackPtr = 0;    /* No pixels on the pixel stack. */
    +    Private->RunningBits = BitsPerPixel + 1; /* Number of bits per code. */
    +    Private->MaxCode1 = 1 << Private->RunningBits; /* Max. code + 1. */
    +    Private->StackPtr = 0; /* No pixels on the pixel stack. */
         Private->LastCode = NO_SUCH_CODE;
    -    Private->CrntShiftState = 0;    /* No information in CrntShiftDWord. */
    +    Private->CrntShiftState = 0; /* No information in CrntShiftDWord. */
         Private->CrntShiftDWord = 0;
     
         Prefix = Private->Prefix;
    -    for (i = 0; i <= LZ_MAX_CODE; i++)
    +    for (i = 0; i <= LZ_MAX_CODE; i++) {
             Prefix[i] = NO_SUCH_CODE;
    +    }
     
         return GIF_OK;
     }
    @@ -869,14 +878,13 @@ DGifSetupDecompress(GifFileType *GifFile)
      This routine can be called few times (one per scan line, for example), in
      order the complete the whole image.
     ******************************************************************************/
    -static int
    -DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
    -{
    +static int DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line,
    +                              int LineLen) {
         int i = 0;
         int j, CrntCode, EOFCode, ClearCode, CrntPrefix, LastCode, StackPtr;
         GifByteType *Stack, *Suffix;
         GifPrefixType *Prefix;
    -    GifFilePrivateType *Private = (GifFilePrivateType *) GifFile->Private;
    +    GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
         StackPtr = Private->StackPtr;
         Prefix = Private->Prefix;
    @@ -891,72 +899,88 @@ DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
         }
     
         if (StackPtr != 0) {
    -        /* Let pop the stack off before continueing to read the GIF file: */
    -        while (StackPtr != 0 && i < LineLen)
    +        /* Let pop the stack off before continueing to read the GIF
    +         * file: */
    +        while (StackPtr != 0 && i < LineLen) {
                 Line[i++] = Stack[--StackPtr];
    +        }
         }
     
    -    while (i < LineLen) {    /* Decode LineLen items. */
    -        if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR)
    +    while (i < LineLen) { /* Decode LineLen items. */
    +        if (DGifDecompressInput(GifFile, &CrntCode) == GIF_ERROR) {
                 return GIF_ERROR;
    +        }
     
             if (CrntCode == EOFCode) {
    -            /* Note however that usually we will not be here as we will stop
    -             * decoding as soon as we got all the pixel, or EOF code will
    -             * not be read at all, and DGifGetLine/Pixel clean everything.  */
    +            /* Note however that usually we will not be here as we
    +             * will stop decoding as soon as we got all the pixel,
    +             * or EOF code will not be read at all, and
    +             * DGifGetLine/Pixel clean everything.  */
                 GifFile->Error = D_GIF_ERR_EOF_TOO_SOON;
                 return GIF_ERROR;
             } else if (CrntCode == ClearCode) {
                 /* We need to start over again: */
    -            for (j = 0; j <= LZ_MAX_CODE; j++)
    +            for (j = 0; j <= LZ_MAX_CODE; j++) {
                     Prefix[j] = NO_SUCH_CODE;
    +            }
                 Private->RunningCode = Private->EOFCode + 1;
                 Private->RunningBits = Private->BitsPerPixel + 1;
                 Private->MaxCode1 = 1 << Private->RunningBits;
                 LastCode = Private->LastCode = NO_SUCH_CODE;
             } else {
    -            /* Its regular code - if in pixel range simply add it to output
    -             * stream, otherwise trace to codes linked list until the prefix
    -             * is in pixel range: */
    +            /* Its regular code - if in pixel range simply add it to
    +             * output stream, otherwise trace to codes linked list
    +             * until the prefix is in pixel range: */
                 if (CrntCode < ClearCode) {
    -                /* This is simple - its pixel scalar, so add it to output: */
    +                /* This is simple - its pixel scalar, so add it
    +                 * to output: */
                     Line[i++] = CrntCode;
                 } else {
    -                /* Its a code to needed to be traced: trace the linked list
    -                 * until the prefix is a pixel, while pushing the suffix
    -                 * pixels on our stack. If we done, pop the stack in reverse
    -                 * (thats what stack is good for!) order to output.  */
    +                /* Its a code to needed to be traced: trace the
    +                 * linked list until the prefix is a pixel,
    +                 * while pushing the suffix pixels on our stack.
    +                 * If we done, pop the stack in reverse (thats
    +                 * what stack is good for!) order to output.  */
                     if (Prefix[CrntCode] == NO_SUCH_CODE) {
                         CrntPrefix = LastCode;
     
    -                    /* Only allowed if CrntCode is exactly the running code:
    -                     * In that case CrntCode = XXXCode, CrntCode or the
    -                     * prefix code is last code and the suffix char is
    -                     * exactly the prefix of last code! */
    -                    if (CrntCode == Private->RunningCode - 2) {
    -                        Suffix[Private->RunningCode - 2] =
    -                           Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
    -                                                                 LastCode,
    -                                                                 ClearCode);
    +                    /* Only allowed if CrntCode is exactly
    +                     * the running code: In that case
    +                     * CrntCode = XXXCode, CrntCode or the
    +                     * prefix code is last code and the
    +                     * suffix char is exactly the prefix of
    +                     * last code! */
    +                    if (CrntCode ==
    +                        Private->RunningCode - 2) {
    +                        Suffix[Private->RunningCode -
    +                               2] = Stack[StackPtr++] =
    +                            DGifGetPrefixChar(
    +                                Prefix, LastCode,
    +                                ClearCode);
                         } else {
    -                        Suffix[Private->RunningCode - 2] =
    -                           Stack[StackPtr++] = DGifGetPrefixChar(Prefix,
    -                                                                 CrntCode,
    -                                                                 ClearCode);
    +                        Suffix[Private->RunningCode -
    +                               2] = Stack[StackPtr++] =
    +                            DGifGetPrefixChar(
    +                                Prefix, CrntCode,
    +                                ClearCode);
                         }
    -                } else
    +                } else {
                         CrntPrefix = CrntCode;
    +                }
     
    -                /* Now (if image is O.K.) we should not get a NO_SUCH_CODE
    -                 * during the trace. As we might loop forever, in case of
    -                 * defective image, we use StackPtr as loop counter and stop
    -                 * before overflowing Stack[]. */
    +                /* Now (if image is O.K.) we should not get a
    +                 * NO_SUCH_CODE during the trace. As we might
    +                 * loop forever, in case of defective image, we
    +                 * use StackPtr as loop counter and stop before
    +                 * overflowing Stack[]. */
                     while (StackPtr < LZ_MAX_CODE &&
    -                       CrntPrefix > ClearCode && CrntPrefix <= LZ_MAX_CODE) {
    +                       CrntPrefix > ClearCode &&
    +                       CrntPrefix <= LZ_MAX_CODE) {
                         Stack[StackPtr++] = Suffix[CrntPrefix];
                         CrntPrefix = Prefix[CrntPrefix];
                     }
    -                if (StackPtr >= LZ_MAX_CODE || CrntPrefix > LZ_MAX_CODE) {
    +                if (StackPtr >= LZ_MAX_CODE ||
    +                    CrntPrefix > LZ_MAX_CODE) {
                         GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
                         return GIF_ERROR;
                     }
    @@ -964,22 +988,29 @@ DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
                     Stack[StackPtr++] = CrntPrefix;
     
                     /* Now lets pop all the stack into output: */
    -                while (StackPtr != 0 && i < LineLen)
    +                while (StackPtr != 0 && i < LineLen) {
                         Line[i++] = Stack[--StackPtr];
    +                }
                 }
    -            if (LastCode != NO_SUCH_CODE && Private->RunningCode - 2 < (LZ_MAX_CODE+1) && Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
    +            if (LastCode != NO_SUCH_CODE &&
    +                Private->RunningCode - 2 < (LZ_MAX_CODE + 1) &&
    +                Prefix[Private->RunningCode - 2] == NO_SUCH_CODE) {
                     Prefix[Private->RunningCode - 2] = LastCode;
     
                     if (CrntCode == Private->RunningCode - 2) {
    -                    /* Only allowed if CrntCode is exactly the running code:
    -                     * In that case CrntCode = XXXCode, CrntCode or the
    -                     * prefix code is last code and the suffix char is
    -                     * exactly the prefix of last code! */
    +                    /* Only allowed if CrntCode is exactly
    +                     * the running code: In that case
    +                     * CrntCode = XXXCode, CrntCode or the
    +                     * prefix code is last code and the
    +                     * suffix char is exactly the prefix of
    +                     * last code! */
                         Suffix[Private->RunningCode - 2] =
    -                       DGifGetPrefixChar(Prefix, LastCode, ClearCode);
    +                        DGifGetPrefixChar(Prefix, LastCode,
    +                                          ClearCode);
                     } else {
                         Suffix[Private->RunningCode - 2] =
    -                       DGifGetPrefixChar(Prefix, CrntCode, ClearCode);
    +                        DGifGetPrefixChar(Prefix, CrntCode,
    +                                          ClearCode);
                     }
                 }
                 LastCode = CrntCode;
    @@ -998,9 +1029,8 @@ DGifDecompressLine(GifFileType *GifFile, GifPixelType *Line, int LineLen)
      If image is defective, we might loop here forever, so we limit the loops to
      the maximum possible if image O.k. - LZ_MAX_CODE times.
     ******************************************************************************/
    -static int
    -DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode)
    -{
    +static int DGifGetPrefixChar(const GifPrefixType *Prefix, int Code,
    +                             int ClearCode) {
         int i = 0;
     
         while (Code > ClearCode && i++ <= LZ_MAX_CODE) {
    @@ -1016,9 +1046,7 @@ DGifGetPrefixChar(GifPrefixType *Prefix, int Code, int ClearCode)
      Interface for accessing the LZ codes directly. Set Code to the real code
      (12bits), or to -1 if EOF code is returned.
     ******************************************************************************/
    -int
    -DGifGetLZCodes(GifFileType *GifFile, int *Code)
    -{
    +int DGifGetLZCodes(GifFileType *GifFile, int *Code) {
         GifByteType *CodeBlock;
         GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
    @@ -1028,15 +1056,18 @@ DGifGetLZCodes(GifFileType *GifFile, int *Code)
             return GIF_ERROR;
         }
     
    -    if (DGifDecompressInput(GifFile, Code) == GIF_ERROR)
    +    if (DGifDecompressInput(GifFile, Code) == GIF_ERROR) {
             return GIF_ERROR;
    +    }
     
         if (*Code == Private->EOFCode) {
    -        /* Skip rest of codes (hopefully only NULL terminating block): */
    +        /* Skip rest of codes (hopefully only NULL terminating block):
    +         */
             do {
    -            if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR)
    +            if (DGifGetCodeNext(GifFile, &CodeBlock) == GIF_ERROR) {
                     return GIF_ERROR;
    -        } while (CodeBlock != NULL) ;
    +            }
    +        } while (CodeBlock != NULL);
     
             *Code = -1;
         } else if (*Code == Private->ClearCode) {
    @@ -1055,15 +1086,10 @@ DGifGetLZCodes(GifFileType *GifFile, int *Code)
      8 bits (bytes) packets, into the real codes.
      Returns GIF_OK if read successfully.
     ******************************************************************************/
    -static int
    -DGifDecompressInput(GifFileType *GifFile, int *Code)
    -{
    +static int DGifDecompressInput(GifFileType *GifFile, int *Code) {
         static const unsigned short CodeMasks[] = {
    -        0x0000, 0x0001, 0x0003, 0x0007,
    -        0x000f, 0x001f, 0x003f, 0x007f,
    -        0x00ff, 0x01ff, 0x03ff, 0x07ff,
    -        0x0fff
    -    };
    +        0x0000, 0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f,
    +        0x007f, 0x00ff, 0x01ff, 0x03ff, 0x07ff, 0x0fff};
     
         GifFilePrivateType *Private = (GifFilePrivateType *)GifFile->Private;
     
    @@ -1077,11 +1103,12 @@ DGifDecompressInput(GifFileType *GifFile, int *Code)
     
         while (Private->CrntShiftState < Private->RunningBits) {
             /* Needs to get more bytes from input stream for next code: */
    -        if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) == GIF_ERROR) {
    +        if (DGifBufferedInput(GifFile, Private->Buf, &NextByte) ==
    +            GIF_ERROR) {
                 return GIF_ERROR;
             }
    -        Private->CrntShiftDWord |=
    -            ((unsigned long)NextByte) << Private->CrntShiftState;
    +        Private->CrntShiftDWord |= ((unsigned long)NextByte)
    +                                   << Private->CrntShiftState;
             Private->CrntShiftState += 8;
         }
         *Code = Private->CrntShiftDWord & CodeMasks[Private->RunningBits];
    @@ -1109,9 +1136,8 @@ DGifDecompressInput(GifFileType *GifFile, int *Code)
      The routine returns the next byte from its internal buffer (or read next
      block in if buffer empty) and returns GIF_OK if succesful.
     ******************************************************************************/
    -static int
    -DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
    -{
    +static int DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf,
    +                             GifByteType *NextByte) {
         if (Buf[0] == 0) {
             /* Needs to read the next buffer - this one is empty: */
             /* coverity[check_return] */
    @@ -1120,8 +1146,8 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
                 return GIF_ERROR;
             }
             /* There shouldn't be any empty data blocks here as the LZW spec
    -         * says the LZW termination code should come first.  Therefore we
    -         * shouldn't be inside this routine at that point.
    +         * says the LZW termination code should come first.  Therefore
    +         * we shouldn't be inside this routine at that point.
              */
             if (Buf[0] == 0) {
                 GifFile->Error = D_GIF_ERR_IMAGE_DEFECT;
    @@ -1132,7 +1158,7 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
                 return GIF_ERROR;
             }
             *NextByte = Buf[1];
    -        Buf[1] = 2;    /* We use now the second place as last char read! */
    +        Buf[1] = 2; /* We use now the second place as last char read! */
             Buf[0]--;
         } else {
             *NextByte = Buf[Buf[1]++];
    @@ -1142,14 +1168,32 @@ DGifBufferedInput(GifFileType *GifFile, GifByteType *Buf, GifByteType *NextByte)
         return GIF_OK;
     }
     
    +/******************************************************************************
    + This routine is called in case of error during parsing image. We need to
    + decrease image counter and reallocate memory for saved images. Not decreasing
    + ImageCount may lead to null pointer dereference, because the last element in
    + SavedImages may point to the spoilt image and null pointer buffers.
    +*******************************************************************************/
    +void DGifDecreaseImageCounter(GifFileType *GifFile) {
    +    GifFile->ImageCount--;
    +    if (GifFile->SavedImages[GifFile->ImageCount].RasterBits != NULL) {
    +        free(GifFile->SavedImages[GifFile->ImageCount].RasterBits);
    +    }
    +
    +    // Realloc array according to the new image counter.
    +    SavedImage *correct_saved_images = (SavedImage *)reallocarray(
    +        GifFile->SavedImages, GifFile->ImageCount, sizeof(SavedImage));
    +    if (correct_saved_images != NULL) {
    +        GifFile->SavedImages = correct_saved_images;
    +    }
    +}
    +
     /******************************************************************************
      This routine reads an entire GIF into core, hanging all its state info off
      the GifFileType pointer.  Call DGifOpenFileName() or DGifOpenFileHandle()
      first to initialize I/O.  Its inverse is EGifSpew().
     *******************************************************************************/
    -int
    -DGifSlurp(GifFileType *GifFile)
    -{
    +int DGifSlurp(GifFileType *GifFile) {
         size_t ImageSize;
         GifRecordType RecordType;
         SavedImage *sp;
    @@ -1160,103 +1204,130 @@ DGifSlurp(GifFileType *GifFile)
         GifFile->ExtensionBlockCount = 0;
     
         do {
    -        if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR)
    +        if (DGifGetRecordType(GifFile, &RecordType) == GIF_ERROR) {
                 return (GIF_ERROR);
    +        }
     
             switch (RecordType) {
    -          case IMAGE_DESC_RECORD_TYPE:
    -              if (DGifGetImageDesc(GifFile) == GIF_ERROR)
    -                  return (GIF_ERROR);
    -
    -              sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
    -              /* Allocate memory for the image */
    -              if (sp->ImageDesc.Width <= 0 || sp->ImageDesc.Height <= 0 ||
    -                      sp->ImageDesc.Width > (INT_MAX / sp->ImageDesc.Height)) {
    -                  return GIF_ERROR;
    -              }
    -              ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
    -
    -              if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
    -                  return GIF_ERROR;
    -              }
    -              sp->RasterBits = (unsigned char *)reallocarray(NULL, ImageSize,
    -                      sizeof(GifPixelType));
    -
    -              if (sp->RasterBits == NULL) {
    -                  return GIF_ERROR;
    -              }
    -
    -              if (sp->ImageDesc.Interlace) {
    -                  int i, j;
    -                   /*
    -                    * The way an interlaced image should be read -
    -                    * offsets and jumps...
    -                    */
    -                  int InterlacedOffset[] = { 0, 4, 2, 1 };
    -                  int InterlacedJumps[] = { 8, 8, 4, 2 };
    -                  /* Need to perform 4 passes on the image */
    -                  for (i = 0; i < 4; i++)
    -                      for (j = InterlacedOffset[i];
    -                       j < sp->ImageDesc.Height;
    -                       j += InterlacedJumps[i]) {
    -                      if (DGifGetLine(GifFile,
    -                              sp->RasterBits+j*sp->ImageDesc.Width,
    -                              sp->ImageDesc.Width) == GIF_ERROR)
    -                          return GIF_ERROR;
    -                      }
    -              }
    -              else {
    -                  if (DGifGetLine(GifFile,sp->RasterBits,ImageSize)==GIF_ERROR)
    -                      return (GIF_ERROR);
    -              }
    -
    -              if (GifFile->ExtensionBlocks) {
    -                  sp->ExtensionBlocks = GifFile->ExtensionBlocks;
    -                  sp->ExtensionBlockCount = GifFile->ExtensionBlockCount;
    -
    -                  GifFile->ExtensionBlocks = NULL;
    -                  GifFile->ExtensionBlockCount = 0;
    -              }
    -              break;
    -
    -          case EXTENSION_RECORD_TYPE:
    -              if (DGifGetExtension(GifFile,&ExtFunction,&ExtData) == GIF_ERROR)
    -                  return (GIF_ERROR);
    -              /* Create an extension block with our data */
    -              if (ExtData != NULL) {
    -                  if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
    -                               &GifFile->ExtensionBlocks,
    -                               ExtFunction, ExtData[0], &ExtData[1])
    -                      == GIF_ERROR)
    -                      return (GIF_ERROR);
    -              }
    -              for (;;) {
    -                  if (DGifGetExtensionNext(GifFile, &ExtData) == GIF_ERROR)
    -                      return (GIF_ERROR);
    -                  if (ExtData == NULL)
    -                      break;
    -                  /* Continue the extension block */
    -                  if (ExtData != NULL)
    -                      if (GifAddExtensionBlock(&GifFile->ExtensionBlockCount,
    -                                   &GifFile->ExtensionBlocks,
    -                                   CONTINUE_EXT_FUNC_CODE,
    -                                   ExtData[0], &ExtData[1]) == GIF_ERROR)
    -                              return (GIF_ERROR);
    -              }
    -              break;
    -
    -          case TERMINATE_RECORD_TYPE:
    -              break;
    -
    -          default:    /* Should be trapped by DGifGetRecordType */
    -              break;
    +        case IMAGE_DESC_RECORD_TYPE:
    +            if (DGifGetImageDesc(GifFile) == GIF_ERROR) {
    +                return (GIF_ERROR);
    +            }
    +
    +            sp = &GifFile->SavedImages[GifFile->ImageCount - 1];
    +            /* Allocate memory for the image */
    +            if (sp->ImageDesc.Width <= 0 ||
    +                sp->ImageDesc.Height <= 0 ||
    +                sp->ImageDesc.Width >
    +                    (INT_MAX / sp->ImageDesc.Height)) {
    +                DGifDecreaseImageCounter(GifFile);
    +                return GIF_ERROR;
    +            }
    +            ImageSize = sp->ImageDesc.Width * sp->ImageDesc.Height;
    +
    +            if (ImageSize > (SIZE_MAX / sizeof(GifPixelType))) {
    +                DGifDecreaseImageCounter(GifFile);
    +                return GIF_ERROR;
    +            }
    +            sp->RasterBits = (unsigned char *)reallocarray(
    +                NULL, ImageSize, sizeof(GifPixelType));
    +
    +            if (sp->RasterBits == NULL) {
    +                DGifDecreaseImageCounter(GifFile);
    +                return GIF_ERROR;
    +            }
    +
    +            if (sp->ImageDesc.Interlace) {
    +                int i, j;
    +                /*
    +                 * The way an interlaced image should be read -
    +                 * offsets and jumps...
    +                 */
    +                static const int InterlacedOffset[] = {0, 4, 2,
    +                                                       1};
    +                static const int InterlacedJumps[] = {8, 8, 4,
    +                                                      2};
    +                /* Need to perform 4 passes on the image */
    +                for (i = 0; i < 4; i++) {
    +                    for (j = InterlacedOffset[i];
    +                         j < sp->ImageDesc.Height;
    +                         j += InterlacedJumps[i]) {
    +                        if (DGifGetLine(
    +                                GifFile,
    +                                sp->RasterBits +
    +                                    j * sp->ImageDesc
    +                                            .Width,
    +                                sp->ImageDesc.Width) ==
    +                            GIF_ERROR) {
    +                            DGifDecreaseImageCounter(
    +                                GifFile);
    +                            return GIF_ERROR;
    +                        }
    +                    }
    +                }
    +            } else {
    +                if (DGifGetLine(GifFile, sp->RasterBits,
    +                                ImageSize) == GIF_ERROR) {
    +                    DGifDecreaseImageCounter(GifFile);
    +                    return GIF_ERROR;
    +                }
    +            }
    +
    +            if (GifFile->ExtensionBlocks) {
    +                sp->ExtensionBlocks = GifFile->ExtensionBlocks;
    +                sp->ExtensionBlockCount =
    +                    GifFile->ExtensionBlockCount;
    +
    +                GifFile->ExtensionBlocks = NULL;
    +                GifFile->ExtensionBlockCount = 0;
    +            }
    +            break;
    +
    +        case EXTENSION_RECORD_TYPE:
    +            if (DGifGetExtension(GifFile, &ExtFunction, &ExtData) ==
    +                GIF_ERROR) {
    +                return (GIF_ERROR);
    +            }
    +            /* Create an extension block with our data */
    +            if (ExtData != NULL) {
    +                if (GifAddExtensionBlock(
    +                        &GifFile->ExtensionBlockCount,
    +                        &GifFile->ExtensionBlocks, ExtFunction,
    +                        ExtData[0], &ExtData[1]) == GIF_ERROR) {
    +                    return (GIF_ERROR);
    +                }
    +            }
    +            for (;;) {
    +                if (DGifGetExtensionNext(GifFile, &ExtData) ==
    +                    GIF_ERROR) {
    +                    return (GIF_ERROR);
    +                }
    +                if (ExtData == NULL) {
    +                    break;
    +                }
    +                /* Continue the extension block */
    +                if (GifAddExtensionBlock(
    +                        &GifFile->ExtensionBlockCount,
    +                        &GifFile->ExtensionBlocks,
    +                        CONTINUE_EXT_FUNC_CODE, ExtData[0],
    +                        &ExtData[1]) == GIF_ERROR) {
    +                    return (GIF_ERROR);
    +                }
    +            }
    +            break;
    +
    +        case TERMINATE_RECORD_TYPE:
    +            break;
    +
    +        default: /* Should be trapped by DGifGetRecordType */
    +            break;
             }
         } while (RecordType != TERMINATE_RECORD_TYPE);
     
         /* Sanity check for corrupted file */
         if (GifFile->ImageCount == 0) {
             GifFile->Error = D_GIF_ERR_NO_IMAG_DSCR;
    -        return(GIF_ERROR);
    +        return (GIF_ERROR);
         }
     
         return (GIF_OK);
    diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c b/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c
    index db08838efff..3b6785f7c63 100644
    --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c
    +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_err.c
    @@ -38,82 +38,80 @@ SPDX-License-Identifier: MIT
     /*****************************************************************************
      Return a string description of  the last GIF error
     *****************************************************************************/
    -const char *
    -GifErrorString(int ErrorCode)
    -{
    +const char *GifErrorString(int ErrorCode) {
         const char *Err;
     
         switch (ErrorCode) {
    -      case E_GIF_ERR_OPEN_FAILED:
    +    case E_GIF_ERR_OPEN_FAILED:
             Err = "Failed to open given file";
             break;
    -      case E_GIF_ERR_WRITE_FAILED:
    +    case E_GIF_ERR_WRITE_FAILED:
             Err = "Failed to write to given file";
             break;
    -      case E_GIF_ERR_HAS_SCRN_DSCR:
    +    case E_GIF_ERR_HAS_SCRN_DSCR:
             Err = "Screen descriptor has already been set";
             break;
    -      case E_GIF_ERR_HAS_IMAG_DSCR:
    +    case E_GIF_ERR_HAS_IMAG_DSCR:
             Err = "Image descriptor is still active";
             break;
    -      case E_GIF_ERR_NO_COLOR_MAP:
    +    case E_GIF_ERR_NO_COLOR_MAP:
             Err = "Neither global nor local color map";
             break;
    -      case E_GIF_ERR_DATA_TOO_BIG:
    +    case E_GIF_ERR_DATA_TOO_BIG:
             Err = "Number of pixels bigger than width * height";
             break;
    -      case E_GIF_ERR_NOT_ENOUGH_MEM:
    +    case E_GIF_ERR_NOT_ENOUGH_MEM:
             Err = "Failed to allocate required memory";
             break;
    -      case E_GIF_ERR_DISK_IS_FULL:
    +    case E_GIF_ERR_DISK_IS_FULL:
             Err = "Write failed (disk full?)";
             break;
    -      case E_GIF_ERR_CLOSE_FAILED:
    +    case E_GIF_ERR_CLOSE_FAILED:
             Err = "Failed to close given file";
             break;
    -      case E_GIF_ERR_NOT_WRITEABLE:
    +    case E_GIF_ERR_NOT_WRITEABLE:
             Err = "Given file was not opened for write";
             break;
    -      case D_GIF_ERR_OPEN_FAILED:
    +    case D_GIF_ERR_OPEN_FAILED:
             Err = "Failed to open given file";
             break;
    -      case D_GIF_ERR_READ_FAILED:
    +    case D_GIF_ERR_READ_FAILED:
             Err = "Failed to read from given file";
             break;
    -      case D_GIF_ERR_NOT_GIF_FILE:
    +    case D_GIF_ERR_NOT_GIF_FILE:
             Err = "Data is not in GIF format";
             break;
    -      case D_GIF_ERR_NO_SCRN_DSCR:
    +    case D_GIF_ERR_NO_SCRN_DSCR:
             Err = "No screen descriptor detected";
             break;
    -      case D_GIF_ERR_NO_IMAG_DSCR:
    +    case D_GIF_ERR_NO_IMAG_DSCR:
             Err = "No Image Descriptor detected";
             break;
    -      case D_GIF_ERR_NO_COLOR_MAP:
    +    case D_GIF_ERR_NO_COLOR_MAP:
             Err = "Neither global nor local color map";
             break;
    -      case D_GIF_ERR_WRONG_RECORD:
    +    case D_GIF_ERR_WRONG_RECORD:
             Err = "Wrong record type detected";
             break;
    -      case D_GIF_ERR_DATA_TOO_BIG:
    +    case D_GIF_ERR_DATA_TOO_BIG:
             Err = "Number of pixels bigger than width * height";
             break;
    -      case D_GIF_ERR_NOT_ENOUGH_MEM:
    +    case D_GIF_ERR_NOT_ENOUGH_MEM:
             Err = "Failed to allocate required memory";
             break;
    -      case D_GIF_ERR_CLOSE_FAILED:
    +    case D_GIF_ERR_CLOSE_FAILED:
             Err = "Failed to close given file";
             break;
    -      case D_GIF_ERR_NOT_READABLE:
    +    case D_GIF_ERR_NOT_READABLE:
             Err = "Given file was not opened for read";
             break;
    -      case D_GIF_ERR_IMAGE_DEFECT:
    +    case D_GIF_ERR_IMAGE_DEFECT:
             Err = "Image is defective, decoding aborted";
             break;
    -      case D_GIF_ERR_EOF_TOO_SOON:
    +    case D_GIF_ERR_EOF_TOO_SOON:
             Err = "Image EOF detected before image complete";
             break;
    -      default:
    +    default:
             Err = NULL;
             break;
         }
    diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h b/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h
    index 6cabd0866ed..bd00af64161 100644
    --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h
    +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_hash.h
    @@ -33,27 +33,25 @@ SPDX-License-Identifier: MIT
     #ifndef _GIF_HASH_H_
     #define _GIF_HASH_H_
     
    -/** Begin JDK modifications to support building on Windows **/
     #ifndef _WIN32
     #include 
    -#endif
    -/** End JDK modifications to support building on Windows **/
    +#endif /* _WIN32 */
     #include 
     
    -#define HT_SIZE         8192    /* 12bits = 4096 or twice as big! */
    -#define HT_KEY_MASK     0x1FFF  /* 13bits keys */
    -#define HT_KEY_NUM_BITS 13      /* 13bits keys */
    -#define HT_MAX_KEY      8191    /* 13bits - 1, maximal code possible */
    -#define HT_MAX_CODE     4095    /* Biggest code possible in 12 bits. */
    +#define HT_SIZE 8192       /* 12bits = 4096 or twice as big! */
    +#define HT_KEY_MASK 0x1FFF /* 13bits keys */
    +#define HT_KEY_NUM_BITS 13 /* 13bits keys */
    +#define HT_MAX_KEY 8191    /* 13bits - 1, maximal code possible */
    +#define HT_MAX_CODE 4095   /* Biggest code possible in 12 bits. */
     
     /* The 32 bits of the long are divided into two parts for the key & code:   */
     /* 1. The code is 12 bits as our compression algorithm is limited to 12bits */
    -/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits.           */
    +/* 2. The key is 12 bits Prefix code + 8 bit new char or 20 bits.        */
     /* The key is the upper 20 bits.  The code is the lower 12. */
    -#define HT_GET_KEY(l)    (l >> 12)
    -#define HT_GET_CODE(l)   (l & 0x0FFF)
    -#define HT_PUT_KEY(l)    (l << 12)
    -#define HT_PUT_CODE(l)   (l & 0x0FFF)
    +#define HT_GET_KEY(l) (l >> 12)
    +#define HT_GET_CODE(l) (l & 0x0FFF)
    +#define HT_PUT_KEY(l) (l << 12)
    +#define HT_PUT_CODE(l) (l & 0x0FFF)
     
     typedef struct GifHashTableType {
         uint32_t HTable[HT_SIZE];
    diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h
    index f739b36adfd..74a2e969c0d 100644
    --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h
    +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib.h
    @@ -39,27 +39,19 @@ extern "C" {
     
     #define GIFLIB_MAJOR 5
     #define GIFLIB_MINOR 2
    -#define GIFLIB_RELEASE 1
    +#define GIFLIB_RELEASE 2
     
    -#define GIF_ERROR   0
    -#define GIF_OK      1
    +#define GIF_ERROR 0
    +#define GIF_OK 1
     
    +#include 
     #include 
    -/** Begin JDK modifications to support building using old compilers**/
    -//#include 
    -#ifdef bool
    -#undef bool
    -#endif
    -typedef int bool;
    -#define false 0
    -#define true 1
    -/** End JDK modifications to support building using old compilers**/
    -
    -#define GIF_STAMP "GIFVER"          /* First chars in file - GIF stamp.  */
    +
    +#define GIF_STAMP "GIFVER" /* First chars in file - GIF stamp.  */
     #define GIF_STAMP_LEN sizeof(GIF_STAMP) - 1
    -#define GIF_VERSION_POS 3           /* Version first character in stamp. */
    -#define GIF87_STAMP "GIF87a"        /* First chars in file - GIF stamp.  */
    -#define GIF89_STAMP "GIF89a"        /* First chars in file - GIF stamp.  */
    +#define GIF_VERSION_POS 3    /* Version first character in stamp. */
    +#define GIF87_STAMP "GIF87a" /* First chars in file - GIF stamp.  */
    +#define GIF89_STAMP "GIF89a" /* First chars in file - GIF stamp.  */
     
     typedef unsigned char GifPixelType;
     typedef unsigned char *GifRowType;
    @@ -75,24 +67,24 @@ typedef struct ColorMapObject {
         int ColorCount;
         int BitsPerPixel;
         bool SortFlag;
    -    GifColorType *Colors;    /* on malloc(3) heap */
    +    GifColorType *Colors; /* on malloc(3) heap */
     } ColorMapObject;
     
     typedef struct GifImageDesc {
    -    GifWord Left, Top, Width, Height;   /* Current image dimensions. */
    -    bool Interlace;                     /* Sequential/Interlaced lines. */
    -    ColorMapObject *ColorMap;           /* The local color map */
    +    GifWord Left, Top, Width, Height; /* Current image dimensions. */
    +    bool Interlace;                   /* Sequential/Interlaced lines. */
    +    ColorMapObject *ColorMap;         /* The local color map */
     } GifImageDesc;
     
     typedef struct ExtensionBlock {
         int ByteCount;
    -    GifByteType *Bytes; /* on malloc(3) heap */
    -    int Function;       /* The block function code */
    -#define CONTINUE_EXT_FUNC_CODE    0x00    /* continuation subblock */
    -#define COMMENT_EXT_FUNC_CODE     0xfe    /* comment */
    -#define GRAPHICS_EXT_FUNC_CODE    0xf9    /* graphics control (GIF89) */
    -#define PLAINTEXT_EXT_FUNC_CODE   0x01    /* plaintext */
    -#define APPLICATION_EXT_FUNC_CODE 0xff    /* application block (GIF89) */
    +    GifByteType *Bytes;            /* on malloc(3) heap */
    +    int Function;                  /* The block function code */
    +#define CONTINUE_EXT_FUNC_CODE 0x00    /* continuation subblock */
    +#define COMMENT_EXT_FUNC_CODE 0xfe     /* comment */
    +#define GRAPHICS_EXT_FUNC_CODE 0xf9    /* graphics control (GIF89) */
    +#define PLAINTEXT_EXT_FUNC_CODE 0x01   /* plaintext */
    +#define APPLICATION_EXT_FUNC_CODE 0xff /* application block (GIF89) */
     } ExtensionBlock;
     
     typedef struct SavedImage {
    @@ -103,22 +95,22 @@ typedef struct SavedImage {
     } SavedImage;
     
     typedef struct GifFileType {
    -    GifWord SWidth, SHeight;         /* Size of virtual canvas */
    -    GifWord SColorResolution;        /* How many colors can we generate? */
    -    GifWord SBackGroundColor;        /* Background color for virtual canvas */
    -    GifByteType AspectByte;          /* Used to compute pixel aspect ratio */
    -    ColorMapObject *SColorMap;       /* Global colormap, NULL if nonexistent. */
    -    int ImageCount;                  /* Number of current image (both APIs) */
    -    GifImageDesc Image;              /* Current image (low-level API) */
    -    SavedImage *SavedImages;         /* Image sequence (high-level API) */
    -    int ExtensionBlockCount;         /* Count extensions past last image */
    +    GifWord SWidth, SHeight;   /* Size of virtual canvas */
    +    GifWord SColorResolution;  /* How many colors can we generate? */
    +    GifWord SBackGroundColor;  /* Background color for virtual canvas */
    +    GifByteType AspectByte;    /* Used to compute pixel aspect ratio */
    +    ColorMapObject *SColorMap; /* Global colormap, NULL if nonexistent. */
    +    int ImageCount;            /* Number of current image (both APIs) */
    +    GifImageDesc Image;        /* Current image (low-level API) */
    +    SavedImage *SavedImages;   /* Image sequence (high-level API) */
    +    int ExtensionBlockCount;   /* Count extensions past last image */
         ExtensionBlock *ExtensionBlocks; /* Extensions past last image */
         int Error;                       /* Last error condition reported */
         void *UserData;                  /* hook to attach user data (TVT) */
         void *Private;                   /* Don't mess with this! */
     } GifFileType;
     
    -#define GIF_ASPECT_RATIO(n)    ((n)+15.0/64.0)
    +#define GIF_ASPECT_RATIO(n) ((n) + 15.0 / 64.0)
     
     typedef enum {
         UNDEFINED_RECORD_TYPE,
    @@ -129,12 +121,12 @@ typedef enum {
     } GifRecordType;
     
     /* func type to read gif data from arbitrary sources (TVT) */
    -typedef int (*InputFunc) (GifFileType *, GifByteType *, int);
    +typedef int (*InputFunc)(GifFileType *, GifByteType *, int);
     
     /* func type to write gif data to arbitrary targets.
      * Returns count of bytes written. (MRB)
      */
    -typedef int (*OutputFunc) (GifFileType *, const GifByteType *, int);
    +typedef int (*OutputFunc)(GifFileType *, const GifByteType *, int);
     
     /******************************************************************************
      GIF89 structures
    @@ -142,14 +134,14 @@ typedef int (*OutputFunc) (GifFileType *, const GifByteType *, int);
     
     typedef struct GraphicsControlBlock {
         int DisposalMode;
    -#define DISPOSAL_UNSPECIFIED      0       /* No disposal specified. */
    -#define DISPOSE_DO_NOT            1       /* Leave image in place */
    -#define DISPOSE_BACKGROUND        2       /* Set area too background color */
    -#define DISPOSE_PREVIOUS          3       /* Restore to previous content */
    -    bool UserInputFlag;      /* User confirmation required before disposal */
    -    int DelayTime;           /* pre-display delay in 0.01sec units */
    -    int TransparentColor;    /* Palette index for transparency, -1 if none */
    -#define NO_TRANSPARENT_COLOR    -1
    +#define DISPOSAL_UNSPECIFIED 0 /* No disposal specified. */
    +#define DISPOSE_DO_NOT 1       /* Leave image in place */
    +#define DISPOSE_BACKGROUND 2   /* Set area too background color */
    +#define DISPOSE_PREVIOUS 3     /* Restore to previous content */
    +    bool UserInputFlag;    /* User confirmation required before disposal */
    +    int DelayTime;         /* pre-display delay in 0.01sec units */
    +    int TransparentColor;  /* Palette index for transparency, -1 if none */
    +#define NO_TRANSPARENT_COLOR -1
     } GraphicsControlBlock;
     
     /******************************************************************************
    @@ -161,49 +153,44 @@ GifFileType *EGifOpenFileName(const char *GifFileName,
                                   const bool GifTestExistence, int *Error);
     GifFileType *EGifOpenFileHandle(const int GifFileHandle, int *Error);
     GifFileType *EGifOpen(void *userPtr, OutputFunc writeFunc, int *Error);
    -int EGifSpew(GifFileType * GifFile);
    +int EGifSpew(GifFileType *GifFile);
     const char *EGifGetGifVersion(GifFileType *GifFile); /* new in 5.x */
     int EGifCloseFile(GifFileType *GifFile, int *ErrorCode);
     
    -#define E_GIF_SUCCEEDED          0
    -#define E_GIF_ERR_OPEN_FAILED    1    /* And EGif possible errors. */
    -#define E_GIF_ERR_WRITE_FAILED   2
    -#define E_GIF_ERR_HAS_SCRN_DSCR  3
    -#define E_GIF_ERR_HAS_IMAG_DSCR  4
    -#define E_GIF_ERR_NO_COLOR_MAP   5
    -#define E_GIF_ERR_DATA_TOO_BIG   6
    +#define E_GIF_SUCCEEDED 0
    +#define E_GIF_ERR_OPEN_FAILED 1 /* And EGif possible errors. */
    +#define E_GIF_ERR_WRITE_FAILED 2
    +#define E_GIF_ERR_HAS_SCRN_DSCR 3
    +#define E_GIF_ERR_HAS_IMAG_DSCR 4
    +#define E_GIF_ERR_NO_COLOR_MAP 5
    +#define E_GIF_ERR_DATA_TOO_BIG 6
     #define E_GIF_ERR_NOT_ENOUGH_MEM 7
    -#define E_GIF_ERR_DISK_IS_FULL   8
    -#define E_GIF_ERR_CLOSE_FAILED   9
    -#define E_GIF_ERR_NOT_WRITEABLE  10
    +#define E_GIF_ERR_DISK_IS_FULL 8
    +#define E_GIF_ERR_CLOSE_FAILED 9
    +#define E_GIF_ERR_NOT_WRITEABLE 10
     
     /* These are legacy.  You probably do not want to call them directly */
    -int EGifPutScreenDesc(GifFileType *GifFile,
    -                      const int GifWidth, const int GifHeight,
    -                      const int GifColorRes,
    +int EGifPutScreenDesc(GifFileType *GifFile, const int GifWidth,
    +                      const int GifHeight, const int GifColorRes,
                           const int GifBackGround,
                           const ColorMapObject *GifColorMap);
    -int EGifPutImageDesc(GifFileType *GifFile,
    -                     const int GifLeft, const int GifTop,
    +int EGifPutImageDesc(GifFileType *GifFile, const int GifLeft, const int GifTop,
                          const int GifWidth, const int GifHeight,
                          const bool GifInterlace,
                          const ColorMapObject *GifColorMap);
     void EGifSetGifVersion(GifFileType *GifFile, const bool gif89);
    -int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine,
    -                int GifLineLen);
    +int EGifPutLine(GifFileType *GifFile, GifPixelType *GifLine, int GifLineLen);
     int EGifPutPixel(GifFileType *GifFile, const GifPixelType GifPixel);
     int EGifPutComment(GifFileType *GifFile, const char *GifComment);
     int EGifPutExtensionLeader(GifFileType *GifFile, const int GifExtCode);
    -int EGifPutExtensionBlock(GifFileType *GifFile,
    -                         const int GifExtLen, const void *GifExtension);
    +int EGifPutExtensionBlock(GifFileType *GifFile, const int GifExtLen,
    +                          const void *GifExtension);
     int EGifPutExtensionTrailer(GifFileType *GifFile);
     int EGifPutExtension(GifFileType *GifFile, const int GifExtCode,
    -                     const int GifExtLen,
    -                     const void *GifExtension);
    +                     const int GifExtLen, const void *GifExtension);
     int EGifPutCode(GifFileType *GifFile, int GifCodeSize,
                     const GifByteType *GifCodeBlock);
    -int EGifPutCodeNext(GifFileType *GifFile,
    -                    const GifByteType *GifCodeBlock);
    +int EGifPutCodeNext(GifFileType *GifFile, const GifByteType *GifCodeBlock);
     
     /******************************************************************************
      GIF decoding routines
    @@ -212,24 +199,25 @@ int EGifPutCodeNext(GifFileType *GifFile,
     /* Main entry points */
     GifFileType *DGifOpenFileName(const char *GifFileName, int *Error);
     GifFileType *DGifOpenFileHandle(int GifFileHandle, int *Error);
    -int DGifSlurp(GifFileType * GifFile);
    -GifFileType *DGifOpen(void *userPtr, InputFunc readFunc, int *Error);    /* new one (TVT) */
    -    int DGifCloseFile(GifFileType * GifFile, int *ErrorCode);
    -
    -#define D_GIF_SUCCEEDED          0
    -#define D_GIF_ERR_OPEN_FAILED    101    /* And DGif possible errors. */
    -#define D_GIF_ERR_READ_FAILED    102
    -#define D_GIF_ERR_NOT_GIF_FILE   103
    -#define D_GIF_ERR_NO_SCRN_DSCR   104
    -#define D_GIF_ERR_NO_IMAG_DSCR   105
    -#define D_GIF_ERR_NO_COLOR_MAP   106
    -#define D_GIF_ERR_WRONG_RECORD   107
    -#define D_GIF_ERR_DATA_TOO_BIG   108
    +int DGifSlurp(GifFileType *GifFile);
    +GifFileType *DGifOpen(void *userPtr, InputFunc readFunc,
    +                      int *Error); /* new one (TVT) */
    +int DGifCloseFile(GifFileType *GifFile, int *ErrorCode);
    +
    +#define D_GIF_SUCCEEDED 0
    +#define D_GIF_ERR_OPEN_FAILED 101 /* And DGif possible errors. */
    +#define D_GIF_ERR_READ_FAILED 102
    +#define D_GIF_ERR_NOT_GIF_FILE 103
    +#define D_GIF_ERR_NO_SCRN_DSCR 104
    +#define D_GIF_ERR_NO_IMAG_DSCR 105
    +#define D_GIF_ERR_NO_COLOR_MAP 106
    +#define D_GIF_ERR_WRONG_RECORD 107
    +#define D_GIF_ERR_DATA_TOO_BIG 108
     #define D_GIF_ERR_NOT_ENOUGH_MEM 109
    -#define D_GIF_ERR_CLOSE_FAILED   110
    -#define D_GIF_ERR_NOT_READABLE   111
    -#define D_GIF_ERR_IMAGE_DEFECT   112
    -#define D_GIF_ERR_EOF_TOO_SOON   113
    +#define D_GIF_ERR_CLOSE_FAILED 110
    +#define D_GIF_ERR_NOT_READABLE 111
    +#define D_GIF_ERR_IMAGE_DEFECT 112
    +#define D_GIF_ERR_EOF_TOO_SOON 113
     
     /* These are legacy.  You probably do not want to call them directly */
     int DGifGetScreenDesc(GifFileType *GifFile);
    @@ -247,11 +235,10 @@ int DGifGetCodeNext(GifFileType *GifFile, GifByteType **GifCodeBlock);
     int DGifGetLZCodes(GifFileType *GifFile, int *GifCode);
     const char *DGifGetGifVersion(GifFileType *GifFile);
     
    -
     /******************************************************************************
      Error handling and reporting.
     ******************************************************************************/
    -extern const char *GifErrorString(int ErrorCode);     /* new in 2012 - ESR */
    +extern const char *GifErrorString(int ErrorCode); /* new in 2012 - ESR */
     
     /*****************************************************************************
      Everything below this point is new after version 1.2, supporting `slurp
    @@ -263,26 +250,26 @@ extern const char *GifErrorString(int ErrorCode);     /* new in 2012 - ESR */
     ******************************************************************************/
     
     extern ColorMapObject *GifMakeMapObject(int ColorCount,
    -                                     const GifColorType *ColorMap);
    +                                        const GifColorType *ColorMap);
     extern void GifFreeMapObject(ColorMapObject *Object);
     extern ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1,
    -                                     const ColorMapObject *ColorIn2,
    -                                     GifPixelType ColorTransIn2[]);
    +                                        const ColorMapObject *ColorIn2,
    +                                        GifPixelType ColorTransIn2[]);
     extern int GifBitSize(int n);
     
     /******************************************************************************
      Support for the in-core structures allocation (slurp mode).
     ******************************************************************************/
     
    -extern void GifApplyTranslation(SavedImage *Image, GifPixelType Translation[]);
    +extern void GifApplyTranslation(SavedImage *Image,
    +                                const GifPixelType Translation[]);
     extern int GifAddExtensionBlock(int *ExtensionBlock_Count,
    -                                ExtensionBlock **ExtensionBlocks,
    -                                int Function,
    +                                ExtensionBlock **ExtensionBlocks, int Function,
                                     unsigned int Len, unsigned char ExtData[]);
     extern void GifFreeExtensions(int *ExtensionBlock_Count,
                                   ExtensionBlock **ExtensionBlocks);
     extern SavedImage *GifMakeSavedImage(GifFileType *GifFile,
    -                                  const SavedImage *CopyFrom);
    +                                     const SavedImage *CopyFrom);
     extern void GifFreeSavedImages(GifFileType *GifFile);
     
     /******************************************************************************
    @@ -295,37 +282,31 @@ int DGifExtensionToGCB(const size_t GifExtensionLength,
     size_t EGifGCBToExtension(const GraphicsControlBlock *GCB,
                               GifByteType *GifExtension);
     
    -int DGifSavedExtensionToGCB(GifFileType *GifFile,
    -                            int ImageIndex,
    +int DGifSavedExtensionToGCB(GifFileType *GifFile, int ImageIndex,
                                 GraphicsControlBlock *GCB);
     int EGifGCBToSavedExtension(const GraphicsControlBlock *GCB,
    -                            GifFileType *GifFile,
    -                            int ImageIndex);
    +                            GifFileType *GifFile, int ImageIndex);
     
     /******************************************************************************
      The library's internal utility font
     ******************************************************************************/
     
    -#define GIF_FONT_WIDTH  8
    +#define GIF_FONT_WIDTH 8
     #define GIF_FONT_HEIGHT 8
     extern const unsigned char GifAsciiTable8x8[][GIF_FONT_WIDTH];
     
    -extern void GifDrawText8x8(SavedImage *Image,
    -                     const int x, const int y,
    -                     const char *legend, const int color);
    +extern void GifDrawText8x8(SavedImage *Image, const int x, const int y,
    +                           const char *legend, const int color);
     
    -extern void GifDrawBox(SavedImage *Image,
    -                    const int x, const int y,
    -                    const int w, const int d, const int color);
    +extern void GifDrawBox(SavedImage *Image, const int x, const int y, const int w,
    +                       const int d, const int color);
     
    -extern void GifDrawRectangle(SavedImage *Image,
    -                   const int x, const int y,
    -                   const int w, const int d, const int color);
    +extern void GifDrawRectangle(SavedImage *Image, const int x, const int y,
    +                             const int w, const int d, const int color);
     
    -extern void GifDrawBoxedText8x8(SavedImage *Image,
    -                          const int x, const int y,
    -                          const char *legend,
    -                          const int border, const int bg, const int fg);
    +extern void GifDrawBoxedText8x8(SavedImage *Image, const int x, const int y,
    +                                const char *legend, const int border,
    +                                const int bg, const int fg);
     
     #ifdef __cplusplus
     }
    diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h
    index 4f832676ffc..f905e0d7b48 100644
    --- a/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h
    +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gif_lib_private.h
    @@ -33,52 +33,54 @@ SPDX-License-Identifier: MIT
     #ifndef _GIF_LIB_PRIVATE_H
     #define _GIF_LIB_PRIVATE_H
     
    -#include "gif_lib.h"
     #include "gif_hash.h"
    +#include "gif_lib.h"
     
     #ifndef SIZE_MAX
    -    #define SIZE_MAX     UINTPTR_MAX
    +#define SIZE_MAX UINTPTR_MAX
     #endif
     
    -#define EXTENSION_INTRODUCER      0x21
    -#define DESCRIPTOR_INTRODUCER     0x2c
    -#define TERMINATOR_INTRODUCER     0x3b
    +#define EXTENSION_INTRODUCER 0x21
    +#define DESCRIPTOR_INTRODUCER 0x2c
    +#define TERMINATOR_INTRODUCER 0x3b
     
    -#define LZ_MAX_CODE         4095    /* Biggest code possible in 12 bits. */
    -#define LZ_BITS             12
    +#define LZ_MAX_CODE 4095 /* Biggest code possible in 12 bits. */
    +#define LZ_BITS 12
     
    -#define FLUSH_OUTPUT        4096    /* Impossible code, to signal flush. */
    -#define FIRST_CODE          4097    /* Impossible code, to signal first. */
    -#define NO_SUCH_CODE        4098    /* Impossible code, to signal empty. */
    +#define FLUSH_OUTPUT 4096 /* Impossible code, to signal flush. */
    +#define FIRST_CODE 4097   /* Impossible code, to signal first. */
    +#define NO_SUCH_CODE 4098 /* Impossible code, to signal empty. */
     
    -#define FILE_STATE_WRITE    0x01
    -#define FILE_STATE_SCREEN   0x02
    -#define FILE_STATE_IMAGE    0x04
    -#define FILE_STATE_READ     0x08
    +#define FILE_STATE_WRITE 0x01
    +#define FILE_STATE_SCREEN 0x02
    +#define FILE_STATE_IMAGE 0x04
    +#define FILE_STATE_READ 0x08
     
    -#define IS_READABLE(Private)    (Private->FileState & FILE_STATE_READ)
    -#define IS_WRITEABLE(Private)   (Private->FileState & FILE_STATE_WRITE)
    +#define IS_READABLE(Private) (Private->FileState & FILE_STATE_READ)
    +#define IS_WRITEABLE(Private) (Private->FileState & FILE_STATE_WRITE)
     
     typedef struct GifFilePrivateType {
    -    GifWord FileState, FileHandle,  /* Where all this data goes to! */
    -      BitsPerPixel,     /* Bits per pixel (Codes uses at least this + 1). */
    -      ClearCode,   /* The CLEAR LZ code. */
    -      EOFCode,     /* The EOF LZ code. */
    -      RunningCode, /* The next code algorithm can generate. */
    -      RunningBits, /* The number of bits required to represent RunningCode. */
    -      MaxCode1,    /* 1 bigger than max. possible code, in RunningBits bits. */
    -      LastCode,    /* The code before the current code. */
    -      CrntCode,    /* Current algorithm code. */
    -      StackPtr,    /* For character stack (see below). */
    -      CrntShiftState;    /* Number of bits in CrntShiftDWord. */
    -    unsigned long CrntShiftDWord;   /* For bytes decomposition into codes. */
    -    unsigned long PixelCount;   /* Number of pixels in image. */
    -    FILE *File;    /* File as stream. */
    -    InputFunc Read;     /* function to read gif input (TVT) */
    -    OutputFunc Write;   /* function to write gif output (MRB) */
    -    GifByteType Buf[256];   /* Compressed input is buffered here. */
    +    GifWord FileState, FileHandle, /* Where all this data goes to! */
    +        BitsPerPixel, /* Bits per pixel (Codes uses at least this + 1). */
    +        ClearCode,    /* The CLEAR LZ code. */
    +        EOFCode,      /* The EOF LZ code. */
    +        RunningCode,  /* The next code algorithm can generate. */
    +        RunningBits,  /* The number of bits required to represent
    +                         RunningCode. */
    +        MaxCode1, /* 1 bigger than max. possible code, in RunningBits bits.
    +                   */
    +        LastCode, /* The code before the current code. */
    +        CrntCode, /* Current algorithm code. */
    +        StackPtr, /* For character stack (see below). */
    +        CrntShiftState;           /* Number of bits in CrntShiftDWord. */
    +    unsigned long CrntShiftDWord; /* For bytes decomposition into codes. */
    +    unsigned long PixelCount;     /* Number of pixels in image. */
    +    FILE *File;                   /* File as stream. */
    +    InputFunc Read;               /* function to read gif input (TVT) */
    +    OutputFunc Write;             /* function to write gif output (MRB) */
    +    GifByteType Buf[256];         /* Compressed input is buffered here. */
         GifByteType Stack[LZ_MAX_CODE]; /* Decoded pixels are stacked here. */
    -    GifByteType Suffix[LZ_MAX_CODE + 1];    /* So we can trace the codes. */
    +    GifByteType Suffix[LZ_MAX_CODE + 1]; /* So we can trace the codes. */
         GifPrefixType Prefix[LZ_MAX_CODE + 1];
         GifHashTableType *HashTable;
         bool gif89;
    diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c b/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c
    index 75b74b4fba0..5aef3044558 100644
    --- a/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c
    +++ b/src/java.desktop/share/native/libsplashscreen/giflib/gifalloc.c
    @@ -30,59 +30,59 @@ SPDX-License-Identifier: MIT
     
     ****************************************************************************/
     
    -#include 
     #include 
    +#include 
     #include 
     
     #include "gif_lib.h"
     #include "gif_lib_private.h"
     
    -#define MAX(x, y)    (((x) > (y)) ? (x) : (y))
    +#define MAX(x, y) (((x) > (y)) ? (x) : (y))
     
     /******************************************************************************
      Miscellaneous utility functions
     ******************************************************************************/
     
     /* return smallest bitfield size n will fit in */
    -int
    -GifBitSize(int n)
    -{
    +int GifBitSize(int n) {
         register int i;
     
    -    for (i = 1; i <= 8; i++)
    -        if ((1 << i) >= n)
    +    for (i = 1; i <= 8; i++) {
    +        if ((1 << i) >= n) {
                 break;
    +        }
    +    }
         return (i);
     }
     
     /******************************************************************************
    -  Color map object functions
    + Color map object functions
     ******************************************************************************/
     
     /*
      * Allocate a color map of given size; initialize with contents of
      * ColorMap if that pointer is non-NULL.
      */
    -ColorMapObject *
    -GifMakeMapObject(int ColorCount, const GifColorType *ColorMap)
    -{
    +ColorMapObject *GifMakeMapObject(int ColorCount, const GifColorType *ColorMap) {
         ColorMapObject *Object;
     
         /*** FIXME: Our ColorCount has to be a power of two.  Is it necessary to
    -     * make the user know that or should we automatically round up instead? */
    +     * make the user know that or should we automatically round up instead?
    +     */
         if (ColorCount != (1 << GifBitSize(ColorCount))) {
    -        return ((ColorMapObject *) NULL);
    +        return ((ColorMapObject *)NULL);
         }
     
         Object = (ColorMapObject *)malloc(sizeof(ColorMapObject));
    -    if (Object == (ColorMapObject *) NULL) {
    -        return ((ColorMapObject *) NULL);
    +    if (Object == (ColorMapObject *)NULL) {
    +        return ((ColorMapObject *)NULL);
         }
     
    -    Object->Colors = (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
    -    if (Object->Colors == (GifColorType *) NULL) {
    +    Object->Colors =
    +        (GifColorType *)calloc(ColorCount, sizeof(GifColorType));
    +    if (Object->Colors == (GifColorType *)NULL) {
             free(Object);
    -        return ((ColorMapObject *) NULL);
    +        return ((ColorMapObject *)NULL);
         }
     
         Object->ColorCount = ColorCount;
    @@ -90,19 +90,17 @@ GifMakeMapObject(int ColorCount, const GifColorType *ColorMap)
         Object->SortFlag = false;
     
         if (ColorMap != NULL) {
    -        memcpy((char *)Object->Colors,
    -               (char *)ColorMap, ColorCount * sizeof(GifColorType));
    +        memcpy((char *)Object->Colors, (char *)ColorMap,
    +               ColorCount * sizeof(GifColorType));
         }
     
         return (Object);
     }
     
     /*******************************************************************************
    -Free a color map object
    + Free a color map object
     *******************************************************************************/
    -void
    -GifFreeMapObject(ColorMapObject *Object)
    -{
    +void GifFreeMapObject(ColorMapObject *Object) {
         if (Object != NULL) {
             (void)free(Object->Colors);
             (void)free(Object);
    @@ -110,17 +108,14 @@ GifFreeMapObject(ColorMapObject *Object)
     }
     
     #ifdef DEBUG
    -void
    -DumpColorMap(ColorMapObject *Object,
    -             FILE * fp)
    -{
    +void DumpColorMap(ColorMapObject *Object, FILE *fp) {
         if (Object != NULL) {
             int i, j, Len = Object->ColorCount;
     
             for (i = 0; i < Len; i += 4) {
                 for (j = 0; j < 4 && j < Len; j++) {
    -                (void)fprintf(fp, "%3d: %02x %02x %02x   ", i + j,
    -                              Object->Colors[i + j].Red,
    +                (void)fprintf(fp, "%3d: %02x %02x %02x   ",
    +                              i + j, Object->Colors[i + j].Red,
                                   Object->Colors[i + j].Green,
                                   Object->Colors[i + j].Blue);
                 }
    @@ -137,11 +132,9 @@ DumpColorMap(ColorMapObject *Object,
      copied iff they didn't exist before.  ColorTransIn2 maps the old
      ColorIn2 into the ColorUnion color map table./
     *******************************************************************************/
    -ColorMapObject *
    -GifUnionColorMap(const ColorMapObject *ColorIn1,
    -              const ColorMapObject *ColorIn2,
    -              GifPixelType ColorTransIn2[])
    -{
    +ColorMapObject *GifUnionColorMap(const ColorMapObject *ColorIn1,
    +                                 const ColorMapObject *ColorIn2,
    +                                 GifPixelType ColorTransIn2[]) {
         int i, j, CrntSlot, RoundUpTo, NewGifBitSize;
         ColorMapObject *ColorUnion;
     
    @@ -152,17 +145,19 @@ GifUnionColorMap(const ColorMapObject *ColorIn1,
          */
     
         /* Allocate table which will hold the result for sure. */
    -    ColorUnion = GifMakeMapObject(MAX(ColorIn1->ColorCount,
    -                               ColorIn2->ColorCount) * 2, NULL);
    +    ColorUnion = GifMakeMapObject(
    +        MAX(ColorIn1->ColorCount, ColorIn2->ColorCount) * 2, NULL);
     
    -    if (ColorUnion == NULL)
    +    if (ColorUnion == NULL) {
             return (NULL);
    +    }
     
         /*
          * Copy ColorIn1 to ColorUnion.
          */
    -    for (i = 0; i < ColorIn1->ColorCount; i++)
    +    for (i = 0; i < ColorIn1->ColorCount; i++) {
             ColorUnion->Colors[i] = ColorIn1->Colors[i];
    +    }
         CrntSlot = ColorIn1->ColorCount;
     
         /*
    @@ -172,22 +167,25 @@ GifUnionColorMap(const ColorMapObject *ColorIn1,
          * of table 1.  This is very useful if your display is limited to
          * 16 colors.
          */
    -    while (ColorIn1->Colors[CrntSlot - 1].Red == 0
    -           && ColorIn1->Colors[CrntSlot - 1].Green == 0
    -           && ColorIn1->Colors[CrntSlot - 1].Blue == 0)
    +    while (ColorIn1->Colors[CrntSlot - 1].Red == 0 &&
    +           ColorIn1->Colors[CrntSlot - 1].Green == 0 &&
    +           ColorIn1->Colors[CrntSlot - 1].Blue == 0) {
             CrntSlot--;
    +    }
     
         /* Copy ColorIn2 to ColorUnion (use old colors if they exist): */
         for (i = 0; i < ColorIn2->ColorCount && CrntSlot <= 256; i++) {
             /* Let's see if this color already exists: */
    -        for (j = 0; j < ColorIn1->ColorCount; j++)
    -            if (memcmp (&ColorIn1->Colors[j], &ColorIn2->Colors[i],
    -                        sizeof(GifColorType)) == 0)
    +        for (j = 0; j < ColorIn1->ColorCount; j++) {
    +            if (memcmp(&ColorIn1->Colors[j], &ColorIn2->Colors[i],
    +                       sizeof(GifColorType)) == 0) {
                     break;
    +            }
    +        }
     
    -        if (j < ColorIn1->ColorCount)
    -            ColorTransIn2[i] = j;    /* color exists in Color1 */
    -        else {
    +        if (j < ColorIn1->ColorCount) {
    +            ColorTransIn2[i] = j; /* color exists in Color1 */
    +        } else {
                 /* Color is new - copy it to a new slot: */
                 ColorUnion->Colors[CrntSlot] = ColorIn2->Colors[i];
                 ColorTransIn2[i] = CrntSlot++;
    @@ -196,7 +194,7 @@ GifUnionColorMap(const ColorMapObject *ColorIn1,
     
         if (CrntSlot > 256) {
             GifFreeMapObject(ColorUnion);
    -        return ((ColorMapObject *) NULL);
    +        return ((ColorMapObject *)NULL);
         }
     
         NewGifBitSize = GifBitSize(CrntSlot);
    @@ -210,16 +208,17 @@ GifUnionColorMap(const ColorMapObject *ColorIn1,
              * We know these slots exist because of the way ColorUnion's
              * start dimension was computed.
              */
    -        for (j = CrntSlot; j < RoundUpTo; j++)
    +        for (j = CrntSlot; j < RoundUpTo; j++) {
                 Map[j].Red = Map[j].Green = Map[j].Blue = 0;
    +        }
     
             /* perhaps we can shrink the map? */
             if (RoundUpTo < ColorUnion->ColorCount) {
    -            GifColorType *new_map = (GifColorType *)reallocarray(Map,
    -                                 RoundUpTo, sizeof(GifColorType));
    -            if( new_map == NULL ) {
    +            GifColorType *new_map = (GifColorType *)reallocarray(
    +                Map, RoundUpTo, sizeof(GifColorType));
    +            if (new_map == NULL) {
                     GifFreeMapObject(ColorUnion);
    -                return ((ColorMapObject *) NULL);
    +                return ((ColorMapObject *)NULL);
                 }
                 ColorUnion->Colors = new_map;
             }
    @@ -234,49 +233,49 @@ GifUnionColorMap(const ColorMapObject *ColorIn1,
     /*******************************************************************************
      Apply a given color translation to the raster bits of an image
     *******************************************************************************/
    -void
    -GifApplyTranslation(SavedImage *Image, GifPixelType Translation[])
    -{
    +void GifApplyTranslation(SavedImage *Image, const GifPixelType Translation[]) {
         register int i;
    -    register int RasterSize = Image->ImageDesc.Height * Image->ImageDesc.Width;
    +    register int RasterSize =
    +        Image->ImageDesc.Height * Image->ImageDesc.Width;
     
    -    for (i = 0; i < RasterSize; i++)
    +    for (i = 0; i < RasterSize; i++) {
             Image->RasterBits[i] = Translation[Image->RasterBits[i]];
    +    }
     }
     
     /******************************************************************************
      Extension record functions
     ******************************************************************************/
    -int
    -GifAddExtensionBlock(int *ExtensionBlockCount,
    -                     ExtensionBlock **ExtensionBlocks,
    -                     int Function,
    -                     unsigned int Len,
    -                     unsigned char ExtData[])
    -{
    +int GifAddExtensionBlock(int *ExtensionBlockCount,
    +                         ExtensionBlock **ExtensionBlocks, int Function,
    +                         unsigned int Len, unsigned char ExtData[]) {
         ExtensionBlock *ep;
     
    -    if (*ExtensionBlocks == NULL)
    -        *ExtensionBlocks=(ExtensionBlock *)malloc(sizeof(ExtensionBlock));
    -    else {
    -        ExtensionBlock* ep_new = (ExtensionBlock *)reallocarray
    -                                      (*ExtensionBlocks, (*ExtensionBlockCount + 1),
    -                                      sizeof(ExtensionBlock));
    -        if( ep_new == NULL )
    +    if (*ExtensionBlocks == NULL) {
    +        *ExtensionBlocks =
    +            (ExtensionBlock *)malloc(sizeof(ExtensionBlock));
    +    } else {
    +        ExtensionBlock *ep_new = (ExtensionBlock *)reallocarray(
    +            *ExtensionBlocks, (*ExtensionBlockCount + 1),
    +            sizeof(ExtensionBlock));
    +        if (ep_new == NULL) {
                 return (GIF_ERROR);
    +        }
             *ExtensionBlocks = ep_new;
         }
     
    -    if (*ExtensionBlocks == NULL)
    +    if (*ExtensionBlocks == NULL) {
             return (GIF_ERROR);
    +    }
     
         ep = &(*ExtensionBlocks)[(*ExtensionBlockCount)++];
     
         ep->Function = Function;
    -    ep->ByteCount=Len;
    +    ep->ByteCount = Len;
         ep->Bytes = (GifByteType *)malloc(ep->ByteCount);
    -    if (ep->Bytes == NULL)
    +    if (ep->Bytes == NULL) {
             return (GIF_ERROR);
    +    }
     
         if (ExtData != NULL) {
             memcpy(ep->Bytes, ExtData, Len);
    @@ -285,38 +284,36 @@ GifAddExtensionBlock(int *ExtensionBlockCount,
         return (GIF_OK);
     }
     
    -void
    -GifFreeExtensions(int *ExtensionBlockCount,
    -                  ExtensionBlock **ExtensionBlocks)
    -{
    +void GifFreeExtensions(int *ExtensionBlockCount,
    +                       ExtensionBlock **ExtensionBlocks) {
         ExtensionBlock *ep;
     
    -    if (*ExtensionBlocks == NULL)
    +    if (*ExtensionBlocks == NULL) {
             return;
    +    }
     
         for (ep = *ExtensionBlocks;
    -         ep < (*ExtensionBlocks + *ExtensionBlockCount);
    -         ep++)
    +         ep < (*ExtensionBlocks + *ExtensionBlockCount); ep++) {
             (void)free((char *)ep->Bytes);
    +    }
         (void)free((char *)*ExtensionBlocks);
         *ExtensionBlocks = NULL;
         *ExtensionBlockCount = 0;
     }
     
     /******************************************************************************
    - Image block allocation functions
    +   Image block allocation functions
     ******************************************************************************/
     
     /* Private Function:
      * Frees the last image in the GifFile->SavedImages array
      */
    -void
    -FreeLastSavedImage(GifFileType *GifFile)
    -{
    +void FreeLastSavedImage(GifFileType *GifFile) {
         SavedImage *sp;
     
    -    if ((GifFile == NULL) || (GifFile->SavedImages == NULL))
    +    if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
             return;
    +    }
     
         /* Remove one SavedImage from the GifFile */
         GifFile->ImageCount--;
    @@ -329,54 +326,58 @@ FreeLastSavedImage(GifFileType *GifFile)
         }
     
         /* Deallocate the image data */
    -    if (sp->RasterBits != NULL)
    +    if (sp->RasterBits != NULL) {
             free((char *)sp->RasterBits);
    +    }
     
         /* Deallocate any extensions */
         GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
     
         /*** FIXME: We could realloc the GifFile->SavedImages structure but is
          * there a point to it? Saves some memory but we'd have to do it every
    -     * time.  If this is used in GifFreeSavedImages then it would be inefficient
    -     * (The whole array is going to be deallocated.)  If we just use it when
    -     * we want to free the last Image it's convenient to do it here.
    +     * time.  If this is used in GifFreeSavedImages then it would be
    +     * inefficient (The whole array is going to be deallocated.)  If we just
    +     * use it when we want to free the last Image it's convenient to do it
    +     * here.
          */
     }
     
     /*
      * Append an image block to the SavedImages array
      */
    -SavedImage *
    -GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
    -{
    -    if (GifFile->SavedImages == NULL)
    +SavedImage *GifMakeSavedImage(GifFileType *GifFile,
    +                              const SavedImage *CopyFrom) {
    +    // cppcheck-suppress ctunullpointer
    +    if (GifFile->SavedImages == NULL) {
             GifFile->SavedImages = (SavedImage *)malloc(sizeof(SavedImage));
    -    else {
    -        SavedImage* newSavedImages = (SavedImage *)reallocarray(GifFile->SavedImages,
    -                               (GifFile->ImageCount + 1), sizeof(SavedImage));
    -        if( newSavedImages == NULL)
    +    } else {
    +        SavedImage *newSavedImages = (SavedImage *)reallocarray(
    +            GifFile->SavedImages, (GifFile->ImageCount + 1),
    +            sizeof(SavedImage));
    +        if (newSavedImages == NULL) {
                 return ((SavedImage *)NULL);
    +        }
             GifFile->SavedImages = newSavedImages;
         }
    -    if (GifFile->SavedImages == NULL)
    +    if (GifFile->SavedImages == NULL) {
             return ((SavedImage *)NULL);
    -    else {
    +    } else {
             SavedImage *sp = &GifFile->SavedImages[GifFile->ImageCount++];
     
             if (CopyFrom != NULL) {
                 memcpy((char *)sp, CopyFrom, sizeof(SavedImage));
     
                 /*
    -             * Make our own allocated copies of the heap fields in the
    -             * copied record.  This guards against potential aliasing
    -             * problems.
    +             * Make our own allocated copies of the heap fields in
    +             * the copied record.  This guards against potential
    +             * aliasing problems.
                  */
     
                 /* first, the local color map */
                 if (CopyFrom->ImageDesc.ColorMap != NULL) {
                     sp->ImageDesc.ColorMap = GifMakeMapObject(
    -                                         CopyFrom->ImageDesc.ColorMap->ColorCount,
    -                                         CopyFrom->ImageDesc.ColorMap->Colors);
    +                    CopyFrom->ImageDesc.ColorMap->ColorCount,
    +                    CopyFrom->ImageDesc.ColorMap->Colors);
                     if (sp->ImageDesc.ColorMap == NULL) {
                         FreeLastSavedImage(GifFile);
                         return (SavedImage *)(NULL);
    @@ -384,32 +385,36 @@ GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
                 }
     
                 /* next, the raster */
    -            sp->RasterBits = (unsigned char *)reallocarray(NULL,
    -                                                  (CopyFrom->ImageDesc.Height *
    -                                                  CopyFrom->ImageDesc.Width),
    -                                                  sizeof(GifPixelType));
    +            sp->RasterBits = (unsigned char *)reallocarray(
    +                NULL,
    +                (CopyFrom->ImageDesc.Height *
    +                 CopyFrom->ImageDesc.Width),
    +                sizeof(GifPixelType));
                 if (sp->RasterBits == NULL) {
                     FreeLastSavedImage(GifFile);
                     return (SavedImage *)(NULL);
                 }
                 memcpy(sp->RasterBits, CopyFrom->RasterBits,
    -                   sizeof(GifPixelType) * CopyFrom->ImageDesc.Height *
    -                   CopyFrom->ImageDesc.Width);
    +                   sizeof(GifPixelType) *
    +                       CopyFrom->ImageDesc.Height *
    +                       CopyFrom->ImageDesc.Width);
     
                 /* finally, the extension blocks */
                 if (CopyFrom->ExtensionBlocks != NULL) {
    -                sp->ExtensionBlocks = (ExtensionBlock *)reallocarray(NULL,
    -                                      CopyFrom->ExtensionBlockCount,
    -                                      sizeof(ExtensionBlock));
    +                sp->ExtensionBlocks =
    +                    (ExtensionBlock *)reallocarray(
    +                        NULL, CopyFrom->ExtensionBlockCount,
    +                        sizeof(ExtensionBlock));
                     if (sp->ExtensionBlocks == NULL) {
                         FreeLastSavedImage(GifFile);
                         return (SavedImage *)(NULL);
                     }
    -                memcpy(sp->ExtensionBlocks, CopyFrom->ExtensionBlocks,
    -                       sizeof(ExtensionBlock) * CopyFrom->ExtensionBlockCount);
    +                memcpy(sp->ExtensionBlocks,
    +                       CopyFrom->ExtensionBlocks,
    +                       sizeof(ExtensionBlock) *
    +                           CopyFrom->ExtensionBlockCount);
                 }
    -        }
    -        else {
    +        } else {
                 memset((char *)sp, '\0', sizeof(SavedImage));
             }
     
    @@ -417,9 +422,7 @@ GifMakeSavedImage(GifFileType *GifFile, const SavedImage *CopyFrom)
         }
     }
     
    -void
    -GifFreeSavedImages(GifFileType *GifFile)
    -{
    +void GifFreeSavedImages(GifFileType *GifFile) {
         SavedImage *sp;
     
         if ((GifFile == NULL) || (GifFile->SavedImages == NULL)) {
    @@ -432,10 +435,12 @@ GifFreeSavedImages(GifFileType *GifFile)
                 sp->ImageDesc.ColorMap = NULL;
             }
     
    -        if (sp->RasterBits != NULL)
    +        if (sp->RasterBits != NULL) {
                 free((char *)sp->RasterBits);
    +        }
     
    -        GifFreeExtensions(&sp->ExtensionBlockCount, &sp->ExtensionBlocks);
    +        GifFreeExtensions(&sp->ExtensionBlockCount,
    +                          &sp->ExtensionBlocks);
         }
         free((char *)GifFile->SavedImages);
         GifFile->SavedImages = NULL;
    diff --git a/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c b/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c
    index 452df69d7cd..7420af674c5 100644
    --- a/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c
    +++ b/src/java.desktop/share/native/libsplashscreen/giflib/openbsd-reallocarray.c
    @@ -28,24 +28,22 @@
      * SPDX-License-Identifier: MIT
      */
     
    -#include 
     #include 
     #include 
     #include 
    +#include 
     
     #ifndef SIZE_MAX
    -    #define SIZE_MAX     UINTPTR_MAX
    +#define SIZE_MAX UINTPTR_MAX
     #endif
     
     /*
      * This is sqrt(SIZE_MAX+1), as s1*s2 <= SIZE_MAX
      * if both s1 < MUL_NO_OVERFLOW and s2 < MUL_NO_OVERFLOW
      */
    -#define MUL_NO_OVERFLOW    ((size_t)1 << (sizeof(size_t) * 4))
    +#define MUL_NO_OVERFLOW ((size_t)1 << (sizeof(size_t) * 4))
     
    -void *
    -openbsd_reallocarray(void *optr, size_t nmemb, size_t size)
    -{
    +void *openbsd_reallocarray(void *optr, size_t nmemb, size_t size) {
         if ((nmemb >= MUL_NO_OVERFLOW || size >= MUL_NO_OVERFLOW) &&
             nmemb > 0 && SIZE_MAX / nmemb < size) {
             errno = ENOMEM;
    @@ -93,7 +91,8 @@ openbsd_reallocarray(void *optr, size_t nmemb, size_t size)
          * fuzzing on one platform may not detect zero-size allocation
          * problems on other platforms.
          */
    -    if (size == 0 || nmemb == 0)
    +    if (size == 0 || nmemb == 0) {
             return NULL;
    +    }
         return realloc(optr, size * nmemb);
     }
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
    index 2d8c585c0e7..441b57ecf1a 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/CHANGES
    @@ -6129,6 +6129,73 @@ Version 1.6.40 [June 21, 2023]
       Updated the configurations and the scripts for continuous integration.
       Cleaned up the code, the build scripts, and the documentation.
     
    +Version 1.6.41 [January 24, 2024]
    +  Added SIMD-optimized code for the LoongArch LSX hardware.
    +    (Contributed by GuXiWei, JinBo and ZhangLixia)
    +  Fixed the run-time discovery of MIPS MSA hardware.
    +    (Contributed by Sui Jingfeng)
    +  Fixed an off-by-one error in the function png_do_check_palette_indexes(),
    +    which failed to recognize errors that might have existed in the first
    +    column of a broken palette-encoded image. This was a benign regression
    +    accidentally introduced in libpng-1.6.33. No pixel was harmed.
    +    (Contributed by Adam Richter; reviewed by John Bowler)
    +  Fixed, improved and modernized the contrib/pngminus programs, i.e.,
    +    png2pnm.c and pnm2png.c
    +  Removed old and peculiar portability hacks that were meant to silence
    +    warnings issued by gcc version 7.1 alone.
    +    (Contributed by John Bowler)
    +  Fixed and modernized the CMake file, and raised the minimum required
    +    CMake version from 3.1 to 3.6.
    +    (Contributed by Clinton Ingram, Timothy Lyanguzov, Tyler Kropp, et al.)
    +  Allowed the configure script to disable the building of auxiliary tools
    +    and tests, thus catching up with the CMake file.
    +    (Contributed by Carlo Bramini)
    +  Fixed a build issue on Mac.
    +    (Contributed by Zixu Wang)
    +  Moved the Autoconf macro files to scripts/autoconf.
    +  Moved the CMake files (except for the main CMakeLists.txt) to
    +    scripts/cmake and moved the list of their contributing authors to
    +    scripts/cmake/AUTHORS.md
    +  Updated the CI configurations and scripts.
    +  Relicensed the CI scripts to the MIT License.
    +  Improved the test coverage.
    +    (Contributed by John Bowler)
    +
    +Version 1.6.42 [January 29, 2024]
    +  Fixed the implementation of the macro function png_check_sig().
    +    This was an API regression, introduced in libpng-1.6.41.
    +    (Reported by Matthieu Darbois)
    +  Fixed and updated the libpng manual.
    +
    +Version 1.6.43 [February 23, 2024]
    +  Fixed the row width check in png_check_IHDR().
    +    This corrected a bug that was specific to the 16-bit platforms,
    +    and removed a spurious compiler warning from the 64-bit builds.
    +    (Reported by Jacek Caban; fixed by John Bowler)
    +  Added eXIf chunk support to the push-mode reader in pngpread.c.
    +    (Contributed by Chris Blume)
    +  Added contrib/pngexif for the benefit of the users who would like
    +    to inspect the content of eXIf chunks.
    +  Added contrib/conftest/basic.dfa, a basic build-time configuration.
    +    (Contributed by John Bowler)
    +  Fixed a preprocessor condition in pngread.c that broke build-time
    +    configurations like contrib/conftest/pngcp.dfa.
    +    (Contributed by John Bowler)
    +  Added CMake build support for LoongArch LSX.
    +    (Contributed by GuXiWei)
    +  Fixed a CMake build error that occurred under a peculiar state of the
    +    dependency tree. This was a regression introduced in libpng-1.6.41.
    +    (Contributed by Dan Rosser)
    +  Marked the installed libpng headers as system headers in CMake.
    +    (Contributed by Benjamin Buch)
    +  Updated the build support for RISCOS.
    +    (Contributed by Cameron Cawley)
    +  Updated the makefiles to allow cross-platform builds to initialize
    +    conventional make variables like AR and ARFLAGS.
    +  Added various improvements to the CI scripts in areas like version
    +    consistency verification and text linting.
    +  Added version consistency verification to pngtest.c also.
    +
     Send comments/corrections/commendations to png-mng-implement at lists.sf.net.
     Subscription is required; visit
     https://lists.sourceforge.net/lists/listinfo/png-mng-implement
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
    index 086d1c2fda6..25f298f0fcf 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/LICENSE
    @@ -4,8 +4,8 @@ COPYRIGHT NOTICE, DISCLAIMER, and LICENSE
     PNG Reference Library License version 2
     ---------------------------------------
     
    - * Copyright (c) 1995-2023 The PNG Reference Library Authors.
    - * Copyright (c) 2018-2023 Cosmin Truta.
    + * Copyright (c) 1995-2024 The PNG Reference Library Authors.
    + * Copyright (c) 2018-2024 Cosmin Truta.
      * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
      * Copyright (c) 1996-1997 Andreas Dilger.
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/README b/src/java.desktop/share/native/libsplashscreen/libpng/README
    index dedd2c1639e..a6ca3ae9f94 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/README
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/README
    @@ -1,4 +1,4 @@
    -README for libpng version 1.6.40
    +README for libpng version 1.6.43
     ================================
     
     See the note about version numbers near the top of `png.h`.
    @@ -142,10 +142,11 @@ Files included in this distribution
         pngwrite.c    =>  High-level write functions
         pngwtran.c    =>  Write data transformations
         pngwutil.c    =>  Write utility functions
    -    arm/          =>  Optimized code for the ARM platform
    -    intel/        =>  Optimized code for the INTEL-SSE2 platform
    -    mips/         =>  Optimized code for the MIPS platform
    -    powerpc/      =>  Optimized code for the PowerPC platform
    +    arm/          =>  Optimized code for ARM Neon
    +    intel/        =>  Optimized code for INTEL SSE2
    +    loongarch/    =>  Optimized code for LoongArch LSX
    +    mips/         =>  Optimized code for MIPS MSA and MIPS MMI
    +    powerpc/      =>  Optimized code for PowerPC VSX
         ci/           =>  Scripts for continuous integration
         contrib/      =>  External contributions
             arm-neon/     =>  Optimized code for the ARM-NEON platform
    @@ -158,6 +159,7 @@ Files included in this distribution
             libtests/     =>  Test programs
             oss-fuzz/     =>  Files used by the OSS-Fuzz project for fuzz-testing
                               libpng
    +        pngexif/      =>  Program to inspect the EXIF information in PNG files
             pngminim/     =>  Minimal decoder, encoder, and progressive decoder
                               programs demonstrating the use of pngusr.dfa
             pngminus/     =>  Simple pnm2png and png2pnm programs
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/UPDATING.txt b/src/java.desktop/share/native/libsplashscreen/libpng/UPDATING.txt
    index 93c8f5bb703..88200db5d73 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/UPDATING.txt
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/UPDATING.txt
    @@ -37,18 +37,21 @@ and instead just tweak the existing one.
     
     First cd into the libpng folder and run the following script.
     
    +    shopt -s nullglob
         for f in *.c *.h;
    -    do
    -      # replace tabs with spaces
    -      expand ${f} > ${f}.tmp;
    -      mv ${f}.tmp $f;
    -
    -      # fix line endings to LF
    -      sed -i -e 's/\r$//g' ${f};
    -
    -      # remove trailing spaces
    -      sed -i -e 's/[ ]* $//g' ${f};
    -    done
    +         do
    +            # replace tabs with spaces
    +            expand ${f} > ${f}.tmp
    +            mv ${f}.tmp $f
    +
    +            # fix line endings to LF
    +            sed -e 's/\r$//g' ${f} > ${f}.tmp
    +            mv ${f}.tmp $f
    +
    +            # remove trailing spaces
    +            sed -e 's/[ ]* $//g' ${f} > ${f}.tmp
    +            mv ${f}.tmp $f
    +         done
     
     6) As with all native code, run it through the official build systems, in case
     the updated code trigger any fatal warnings with the official compilers.
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.c b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
    index 91a92e5f718..232dff876c7 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/png.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.c
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * Copyright (c) 2018-2023 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -42,27 +42,7 @@
     #include "pngpriv.h"
     
     /* Generate a compiler error if there is an old png.h in the search path. */
    -typedef png_libpng_version_1_6_40 Your_png_h_is_not_version_1_6_40;
    -
    -#ifdef __GNUC__
    -/* The version tests may need to be added to, but the problem warning has
    - * consistently been fixed in GCC versions which obtain wide-spread release.
    - * The problem is that many versions of GCC rearrange comparison expressions in
    - * the optimizer in such a way that the results of the comparison will change
    - * if signed integer overflow occurs.  Such comparisons are not permitted in
    - * ANSI C90, however GCC isn't clever enough to work out that that do not occur
    - * below in png_ascii_from_fp and png_muldiv, so it produces a warning with
    - * -Wextra.  Unfortunately this is highly dependent on the optimizer and the
    - * machine architecture so the warning comes and goes unpredictably and is
    - * impossible to "fix", even were that a good idea.
    - */
    -#if __GNUC__ == 7 && __GNUC_MINOR__ == 1
    -#define GCC_STRICT_OVERFLOW 1
    -#endif /* GNU 7.1.x */
    -#endif /* GNU */
    -#ifndef GCC_STRICT_OVERFLOW
    -#define GCC_STRICT_OVERFLOW 0
    -#endif
    +typedef png_libpng_version_1_6_43 Your_png_h_is_not_version_1_6_43;
     
     /* Tells libpng that we have already handled the first "num_bytes" bytes
      * of the PNG file signature.  If the PNG data is embedded into another
    @@ -101,21 +81,21 @@ png_set_sig_bytes(png_structrp png_ptr, int num_bytes)
     int PNGAPI
     png_sig_cmp(png_const_bytep sig, size_t start, size_t num_to_check)
     {
    -   png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
    +   static const png_byte png_signature[8] = {137, 80, 78, 71, 13, 10, 26, 10};
     
        if (num_to_check > 8)
           num_to_check = 8;
     
        else if (num_to_check < 1)
    -      return (-1);
    +      return -1;
     
        if (start > 7)
    -      return (-1);
    +      return -1;
     
        if (start + num_to_check > 8)
           num_to_check = 8 - start;
     
    -   return ((int)(memcmp(&sig[start], &png_signature[start], num_to_check)));
    +   return memcmp(&sig[start], &png_signature[start], num_to_check);
     }
     
     #endif /* READ */
    @@ -475,7 +455,6 @@ png_info_init_3,(png_infopp ptr_ptr, size_t png_info_struct_size),
        memset(info_ptr, 0, (sizeof *info_ptr));
     }
     
    -/* The following API is not called internally */
     void PNGAPI
     png_data_freer(png_const_structrp png_ptr, png_inforp info_ptr,
         int freer, png_uint_32 mask)
    @@ -714,9 +693,9 @@ png_voidp PNGAPI
     png_get_io_ptr(png_const_structrp png_ptr)
     {
        if (png_ptr == NULL)
    -      return (NULL);
    +      return NULL;
     
    -   return (png_ptr->io_ptr);
    +   return png_ptr->io_ptr;
     }
     
     #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
    @@ -780,7 +759,7 @@ png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime)
     
        {
           size_t pos = 0;
    -      char number_buf[5]; /* enough for a four-digit year */
    +      char number_buf[5] = {0, 0, 0, 0, 0}; /* enough for a four-digit year */
     
     #     define APPEND_STRING(string) pos = png_safecat(out, 29, pos, (string))
     #     define APPEND_NUMBER(format, value)\
    @@ -843,8 +822,8 @@ png_get_copyright(png_const_structrp png_ptr)
        return PNG_STRING_COPYRIGHT
     #else
        return PNG_STRING_NEWLINE \
    -      "libpng version 1.6.40" PNG_STRING_NEWLINE \
    -      "Copyright (c) 2018-2023 Cosmin Truta" PNG_STRING_NEWLINE \
    +      "libpng version 1.6.43" PNG_STRING_NEWLINE \
    +      "Copyright (c) 2018-2024 Cosmin Truta" PNG_STRING_NEWLINE \
           "Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson" \
           PNG_STRING_NEWLINE \
           "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \
    @@ -1005,7 +984,7 @@ png_reset_zstream(png_structrp png_ptr)
           return Z_STREAM_ERROR;
     
        /* WARNING: this resets the window bits to the maximum! */
    -   return (inflateReset(&png_ptr->zstream));
    +   return inflateReset(&png_ptr->zstream);
     }
     #endif /* READ */
     
    @@ -1014,7 +993,7 @@ png_uint_32 PNGAPI
     png_access_version_number(void)
     {
        /* Version of *.c files used when building libpng */
    -   return((png_uint_32)PNG_LIBPNG_VER);
    +   return (png_uint_32)PNG_LIBPNG_VER;
     }
     
     #if defined(PNG_READ_SUPPORTED) || defined(PNG_WRITE_SUPPORTED)
    @@ -1870,14 +1849,14 @@ png_icc_profile_error(png_const_structrp png_ptr, png_colorspacerp colorspace,
        }
     #  ifdef PNG_WARNINGS_SUPPORTED
        else
    -      {
    -         char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114 */
    +   {
    +      char number[PNG_NUMBER_BUFFER_SIZE]; /* +24 = 114 */
     
    -         pos = png_safecat(message, (sizeof message), pos,
    -             png_format_number(number, number+(sizeof number),
    -             PNG_NUMBER_FORMAT_x, value));
    -         pos = png_safecat(message, (sizeof message), pos, "h: "); /* +2 = 116 */
    -      }
    +      pos = png_safecat(message, (sizeof message), pos,
    +          png_format_number(number, number+(sizeof number),
    +          PNG_NUMBER_FORMAT_x, value));
    +      pos = png_safecat(message, (sizeof message), pos, "h: "); /* +2 = 116 */
    +   }
     #  endif
        /* The 'reason' is an arbitrary message, allow +79 maximum 195 */
        pos = png_safecat(message, (sizeof message), pos, reason);
    @@ -2560,17 +2539,6 @@ png_colorspace_set_rgb_coefficients(png_structrp png_ptr)
     
     #endif /* COLORSPACE */
     
    -#ifdef __GNUC__
    -/* This exists solely to work round a warning from GNU C. */
    -static int /* PRIVATE */
    -png_gt(size_t a, size_t b)
    -{
    -   return a > b;
    -}
    -#else
    -#   define png_gt(a,b) ((a) > (b))
    -#endif
    -
     void /* PRIVATE */
     png_check_IHDR(png_const_structrp png_ptr,
         png_uint_32 width, png_uint_32 height, int bit_depth,
    @@ -2592,8 +2560,16 @@ png_check_IHDR(png_const_structrp png_ptr,
           error = 1;
        }
     
    -   if (png_gt(((width + 7) & (~7U)),
    -       ((PNG_SIZE_MAX
    +   /* The bit mask on the first line below must be at least as big as a
    +    * png_uint_32.  "~7U" is not adequate on 16-bit systems because it will
    +    * be an unsigned 16-bit value.  Casting to (png_alloc_size_t) makes the
    +    * type of the result at least as bit (in bits) as the RHS of the > operator
    +    * which also avoids a common warning on 64-bit systems that the comparison
    +    * of (png_uint_32) against the constant value on the RHS will always be
    +    * false.
    +    */
    +   if (((width + 7) & ~(png_alloc_size_t)7) >
    +       (((PNG_SIZE_MAX
                - 48        /* big_row_buf hack */
                - 1)        /* filter byte */
                / 8)        /* 8-byte RGBA pixels */
    @@ -2919,14 +2895,6 @@ png_pow10(int power)
     /* Function to format a floating point value in ASCII with a given
      * precision.
      */
    -#if GCC_STRICT_OVERFLOW
    -#pragma GCC diagnostic push
    -/* The problem arises below with exp_b10, which can never overflow because it
    - * comes, originally, from frexp and is therefore limited to a range which is
    - * typically +/-710 (log2(DBL_MAX)/log2(DBL_MIN)).
    - */
    -#pragma GCC diagnostic warning "-Wstrict-overflow=2"
    -#endif /* GCC_STRICT_OVERFLOW */
     void /* PRIVATE */
     png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size,
         double fp, unsigned int precision)
    @@ -3248,10 +3216,6 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, size_t size,
        /* Here on buffer too small. */
        png_error(png_ptr, "ASCII conversion buffer too small");
     }
    -#if GCC_STRICT_OVERFLOW
    -#pragma GCC diagnostic pop
    -#endif /* GCC_STRICT_OVERFLOW */
    -
     #  endif /* FLOATING_POINT */
     
     #  ifdef PNG_FIXED_POINT_SUPPORTED
    @@ -3279,7 +3243,7 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii,
           if (num <= 0x80000000) /* else overflowed */
           {
              unsigned int ndigits = 0, first = 16 /* flag value */;
    -         char digits[10];
    +         char digits[10] = {0};
     
              while (num)
              {
    @@ -3364,15 +3328,6 @@ png_fixed(png_const_structrp png_ptr, double fp, png_const_charp text)
      * the nearest .00001).  Overflow and divide by zero are signalled in
      * the result, a boolean - true on success, false on overflow.
      */
    -#if GCC_STRICT_OVERFLOW /* from above */
    -/* It is not obvious which comparison below gets optimized in such a way that
    - * signed overflow would change the result; looking through the code does not
    - * reveal any tests which have the form GCC complains about, so presumably the
    - * optimizer is moving an add or subtract into the 'if' somewhere.
    - */
    -#pragma GCC diagnostic push
    -#pragma GCC diagnostic warning "-Wstrict-overflow=2"
    -#endif /* GCC_STRICT_OVERFLOW */
     int
     png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
         png_int_32 divisor)
    @@ -3487,9 +3442,6 @@ png_muldiv(png_fixed_point_p res, png_fixed_point a, png_int_32 times,
     
        return 0;
     }
    -#if GCC_STRICT_OVERFLOW
    -#pragma GCC diagnostic pop
    -#endif /* GCC_STRICT_OVERFLOW */
     #endif /* READ_GAMMA || INCH_CONVERSIONS */
     
     #if defined(PNG_READ_GAMMA_SUPPORTED) || defined(PNG_INCH_CONVERSIONS_SUPPORTED)
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/png.h b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
    index 578841c9580..9f61a773c1d 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/png.h
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/png.h
    @@ -29,9 +29,9 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * libpng version 1.6.40
    + * libpng version 1.6.43
      *
    - * Copyright (c) 2018-2023 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -43,7 +43,7 @@
      *   libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger
      *   libpng versions 0.97, January 1998, through 1.6.35, July 2018:
      *     Glenn Randers-Pehrson
    - *   libpng versions 1.6.36, December 2018, through 1.6.40, June 2023:
    + *   libpng versions 1.6.36, December 2018, through 1.6.43, February 2024:
      *     Cosmin Truta
      *   See also "Contributing Authors", below.
      */
    @@ -55,8 +55,8 @@
      * PNG Reference Library License version 2
      * ---------------------------------------
      *
    - *  * Copyright (c) 1995-2023 The PNG Reference Library Authors.
    - *  * Copyright (c) 2018-2023 Cosmin Truta.
    + *  * Copyright (c) 1995-2024 The PNG Reference Library Authors.
    + *  * Copyright (c) 2018-2024 Cosmin Truta.
      *  * Copyright (c) 2000-2002, 2004, 2006-2018 Glenn Randers-Pehrson.
      *  * Copyright (c) 1996-1997 Andreas Dilger.
      *  * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -267,7 +267,7 @@
      *    ...
      *    1.5.30                  15    10530  15.so.15.30[.0]
      *    ...
    - *    1.6.40                  16    10640  16.so.16.40[.0]
    + *    1.6.43                  16    10643  16.so.16.43[.0]
      *
      *    Henceforth the source version will match the shared-library major and
      *    minor numbers; the shared-library major version number will be used for
    @@ -283,9 +283,6 @@
      *    to the info_ptr or png_ptr members through png.h, and the compiled
      *    application is loaded with a different version of the library.
      *
    - *    DLLNUM will change each time there are forward or backward changes
    - *    in binary compatibility (e.g., when a new feature is added).
    - *
      * See libpng.txt or libpng.3 for more information.  The PNG specification
      * is available as a W3C Recommendation and as an ISO/IEC Standard; see
      * 
    @@ -306,19 +303,21 @@
      */
     
     /* Version information for png.h - this should match the version in png.c */
    -#define PNG_LIBPNG_VER_STRING "1.6.40"
    -#define PNG_HEADER_VERSION_STRING " libpng version 1.6.40 - June 21, 2023\n"
    +#define PNG_LIBPNG_VER_STRING "1.6.43"
    +#define PNG_HEADER_VERSION_STRING " libpng version " PNG_LIBPNG_VER_STRING "\n"
     
    -#define PNG_LIBPNG_VER_SONUM   16
    -#define PNG_LIBPNG_VER_DLLNUM  16
    +/* The versions of shared library builds should stay in sync, going forward */
    +#define PNG_LIBPNG_VER_SHAREDLIB 16
    +#define PNG_LIBPNG_VER_SONUM     PNG_LIBPNG_VER_SHAREDLIB /* [Deprecated] */
    +#define PNG_LIBPNG_VER_DLLNUM    PNG_LIBPNG_VER_SHAREDLIB /* [Deprecated] */
     
     /* These should match the first 3 components of PNG_LIBPNG_VER_STRING: */
     #define PNG_LIBPNG_VER_MAJOR   1
     #define PNG_LIBPNG_VER_MINOR   6
    -#define PNG_LIBPNG_VER_RELEASE 40
    +#define PNG_LIBPNG_VER_RELEASE 43
     
     /* This should be zero for a public release, or non-zero for a
    - * development version.  [Deprecated]
    + * development version.
      */
     #define PNG_LIBPNG_VER_BUILD  0
     
    @@ -346,7 +345,7 @@
      * From version 1.0.1 it is:
      * XXYYZZ, where XX=major, YY=minor, ZZ=release
      */
    -#define PNG_LIBPNG_VER 10640 /* 1.6.40 */
    +#define PNG_LIBPNG_VER 10643 /* 1.6.43 */
     
     /* Library configuration: these options cannot be changed after
      * the library has been built.
    @@ -456,7 +455,7 @@ extern "C" {
     /* This triggers a compiler error in png.c, if png.c and png.h
      * do not agree upon the version number.
      */
    -typedef char* png_libpng_version_1_6_40;
    +typedef char* png_libpng_version_1_6_43;
     
     /* Basic control structions.  Read libpng-manual.txt or libpng.3 for more info.
      *
    @@ -877,7 +876,7 @@ PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef);
     #define PNG_TRANSFORM_GRAY_TO_RGB   0x2000      /* read only */
     /* Added to libpng-1.5.4 */
     #define PNG_TRANSFORM_EXPAND_16     0x4000      /* read only */
    -#if INT_MAX >= 0x8000 /* else this might break */
    +#if ~0U > 0xffffU /* or else this might break on a 16-bit machine */
     #define PNG_TRANSFORM_SCALE_16      0x8000      /* read only */
     #endif
     
    @@ -936,15 +935,15 @@ PNG_EXPORT(2, void, png_set_sig_bytes, (png_structrp png_ptr, int num_bytes));
     /* Check sig[start] through sig[start + num_to_check - 1] to see if it's a
      * PNG file.  Returns zero if the supplied bytes match the 8-byte PNG
      * signature, and non-zero otherwise.  Having num_to_check == 0 or
    - * start > 7 will always fail (ie return non-zero).
    + * start > 7 will always fail (i.e. return non-zero).
      */
     PNG_EXPORT(3, int, png_sig_cmp, (png_const_bytep sig, size_t start,
         size_t num_to_check));
     
     /* Simple signature checking function.  This is the same as calling
    - * png_check_sig(sig, n) := !png_sig_cmp(sig, 0, n).
    + * png_check_sig(sig, n) := (png_sig_cmp(sig, 0, n) == 0).
      */
    -#define png_check_sig(sig, n) !png_sig_cmp((sig), 0, (n))
    +#define png_check_sig(sig, n) (png_sig_cmp((sig), 0, (n)) == 0) /* DEPRECATED */
     
     /* Allocate and initialize png_ptr struct for reading, and any other memory. */
     PNG_EXPORTA(4, png_structp, png_create_read_struct,
    @@ -1758,12 +1757,9 @@ PNG_EXPORT(97, void, png_free, (png_const_structrp png_ptr, png_voidp ptr));
     PNG_EXPORT(98, void, png_free_data, (png_const_structrp png_ptr,
         png_inforp info_ptr, png_uint_32 free_me, int num));
     
    -/* Reassign responsibility for freeing existing data, whether allocated
    +/* Reassign the responsibility for freeing existing data, whether allocated
      * by libpng or by the application; this works on the png_info structure passed
    - * in, it does not change the state for other png_info structures.
    - *
    - * It is unlikely that this function works correctly as of 1.6.0 and using it
    - * may result either in memory leaks or double free of allocated data.
    + * in, without changing the state for other png_info structures.
      */
     PNG_EXPORT(99, void, png_data_freer, (png_const_structrp png_ptr,
         png_inforp info_ptr, int freer, png_uint_32 mask));
    @@ -3235,11 +3231,18 @@ PNG_EXPORT(245, int, png_image_write_to_memory, (png_imagep image, void *memory,
     #ifdef PNG_MIPS_MSA_API_SUPPORTED
     #  define PNG_MIPS_MSA   6 /* HARDWARE: MIPS Msa SIMD instructions supported */
     #endif
    -#define PNG_IGNORE_ADLER32 8
    +#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED
    +#  define PNG_IGNORE_ADLER32 8 /* SOFTWARE: disable Adler32 check on IDAT */
    +#endif
     #ifdef PNG_POWERPC_VSX_API_SUPPORTED
    -#  define PNG_POWERPC_VSX   10 /* HARDWARE: PowerPC VSX SIMD instructions supported */
    +#  define PNG_POWERPC_VSX   10 /* HARDWARE: PowerPC VSX SIMD instructions
    +                                * supported */
     #endif
    -#define PNG_OPTION_NEXT  12 /* Next option - numbers must be even */
    +#ifdef PNG_MIPS_MMI_API_SUPPORTED
    +#  define PNG_MIPS_MMI   12 /* HARDWARE: MIPS MMI SIMD instructions supported */
    +#endif
    +
    +#define PNG_OPTION_NEXT  14 /* Next option - numbers must be even */
     
     /* Return values: NOTE: there are four values and 'off' is *not* zero */
     #define PNG_OPTION_UNSET   0 /* Unset - defaults to off */
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
    index 41cbc91d398..b3b441b1122 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngconf.h
    @@ -29,9 +29,9 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * libpng version 1.6.40
    + * libpng version 1.6.43
      *
    - * Copyright (c) 2018-2022 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2016,2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
    index 623735f06f1..ea8dd172197 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngerror.c
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * Copyright (c) 2018 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2017 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -283,7 +283,7 @@ void
     png_warning_parameter_unsigned(png_warning_parameters p, int number, int format,
         png_alloc_size_t value)
     {
    -   char buffer[PNG_NUMBER_BUFFER_SIZE];
    +   char buffer[PNG_NUMBER_BUFFER_SIZE] = {0};
        png_warning_parameter(p, number, PNG_FORMAT_NUMBER(buffer, format, value));
     }
     
    @@ -293,7 +293,7 @@ png_warning_parameter_signed(png_warning_parameters p, int number, int format,
     {
        png_alloc_size_t u;
        png_charp str;
    -   char buffer[PNG_NUMBER_BUFFER_SIZE];
    +   char buffer[PNG_NUMBER_BUFFER_SIZE] = {0};
     
        /* Avoid overflow by doing the negate in a png_alloc_size_t: */
        u = (png_alloc_size_t)value;
    @@ -886,7 +886,7 @@ png_get_error_ptr(png_const_structrp png_ptr)
        if (png_ptr == NULL)
           return NULL;
     
    -   return ((png_voidp)png_ptr->error_ptr);
    +   return (png_voidp)png_ptr->error_ptr;
     }
     
     
    @@ -961,31 +961,25 @@ png_safe_warning(png_structp png_nonconst_ptr, png_const_charp warning_message)
     #endif
     
     int /* PRIVATE */
    -png_safe_execute(png_imagep image_in, int (*function)(png_voidp), png_voidp arg)
    +png_safe_execute(png_imagep image, int (*function)(png_voidp), png_voidp arg)
     {
    -   volatile png_imagep image = image_in;
    -   volatile int result;
    -   volatile png_voidp saved_error_buf;
    +   png_voidp saved_error_buf = image->opaque->error_buf;
        jmp_buf safe_jmpbuf;
    +   int result;
     
    -   /* Safely execute function(arg) with png_error returning to this function. */
    -   saved_error_buf = image->opaque->error_buf;
    -   result = setjmp(safe_jmpbuf) == 0;
    -
    -   if (result != 0)
    +   /* Safely execute function(arg), with png_error returning back here. */
    +   if (setjmp(safe_jmpbuf) == 0)
        {
    -
           image->opaque->error_buf = safe_jmpbuf;
           result = function(arg);
    +      image->opaque->error_buf = saved_error_buf;
    +      return result;
        }
     
    +   /* On png_error, return via longjmp, pop the jmpbuf, and free the image. */
        image->opaque->error_buf = saved_error_buf;
    -
    -   /* And do the cleanup prior to any failure return. */
    -   if (result == 0)
    -      png_image_free(image);
    -
    -   return result;
    +   png_image_free(image);
    +   return 0;
     }
     #endif /* SIMPLIFIED READ || SIMPLIFIED_WRITE */
     #endif /* READ || WRITE */
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
    index 6e510b27327..41e0a5abc3a 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngget.c
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * Copyright (c) 2018-2023 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -56,22 +56,22 @@ png_get_valid(png_const_structrp png_ptr, png_const_inforp info_ptr,
            * valid tRNS chunk in this case.
            */
           if (flag == PNG_INFO_tRNS && png_ptr->num_trans == 0)
    -         return(0);
    +         return 0;
     #endif
     
    -      return(info_ptr->valid & flag);
    +      return info_ptr->valid & flag;
        }
     
    -   return(0);
    +   return 0;
     }
     
     size_t PNGAPI
     png_get_rowbytes(png_const_structrp png_ptr, png_const_inforp info_ptr)
     {
        if (png_ptr != NULL && info_ptr != NULL)
    -      return(info_ptr->rowbytes);
    +      return info_ptr->rowbytes;
     
    -   return(0);
    +   return 0;
     }
     
     #ifdef PNG_INFO_IMAGE_SUPPORTED
    @@ -79,9 +79,9 @@ png_bytepp PNGAPI
     png_get_rows(png_const_structrp png_ptr, png_const_inforp info_ptr)
     {
        if (png_ptr != NULL && info_ptr != NULL)
    -      return(info_ptr->row_pointers);
    +      return info_ptr->row_pointers;
     
    -   return(0);
    +   return 0;
     }
     #endif
     
    @@ -93,7 +93,7 @@ png_get_image_width(png_const_structrp png_ptr, png_const_inforp info_ptr)
        if (png_ptr != NULL && info_ptr != NULL)
           return info_ptr->width;
     
    -   return (0);
    +   return 0;
     }
     
     png_uint_32 PNGAPI
    @@ -102,7 +102,7 @@ png_get_image_height(png_const_structrp png_ptr, png_const_inforp info_ptr)
        if (png_ptr != NULL && info_ptr != NULL)
           return info_ptr->height;
     
    -   return (0);
    +   return 0;
     }
     
     png_byte PNGAPI
    @@ -111,7 +111,7 @@ png_get_bit_depth(png_const_structrp png_ptr, png_const_inforp info_ptr)
        if (png_ptr != NULL && info_ptr != NULL)
           return info_ptr->bit_depth;
     
    -   return (0);
    +   return 0;
     }
     
     png_byte PNGAPI
    @@ -120,7 +120,7 @@ png_get_color_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
        if (png_ptr != NULL && info_ptr != NULL)
           return info_ptr->color_type;
     
    -   return (0);
    +   return 0;
     }
     
     png_byte PNGAPI
    @@ -129,7 +129,7 @@ png_get_filter_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
        if (png_ptr != NULL && info_ptr != NULL)
           return info_ptr->filter_type;
     
    -   return (0);
    +   return 0;
     }
     
     png_byte PNGAPI
    @@ -138,7 +138,7 @@ png_get_interlace_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
        if (png_ptr != NULL && info_ptr != NULL)
           return info_ptr->interlace_type;
     
    -   return (0);
    +   return 0;
     }
     
     png_byte PNGAPI
    @@ -147,7 +147,7 @@ png_get_compression_type(png_const_structrp png_ptr, png_const_inforp info_ptr)
        if (png_ptr != NULL && info_ptr != NULL)
           return info_ptr->compression_type;
     
    -   return (0);
    +   return 0;
     }
     
     png_uint_32 PNGAPI
    @@ -155,21 +155,20 @@ png_get_x_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
        info_ptr)
     {
     #ifdef PNG_pHYs_SUPPORTED
    +   png_debug(1, "in png_get_x_pixels_per_meter");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_pHYs) != 0)
    -      {
    -         png_debug1(1, "in %s retrieval function",
    -             "png_get_x_pixels_per_meter");
    -
    -         if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
    -            return (info_ptr->x_pixels_per_unit);
    -      }
    +   {
    +      if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
    +         return info_ptr->x_pixels_per_unit;
    +   }
     #else
        PNG_UNUSED(png_ptr)
        PNG_UNUSED(info_ptr)
     #endif
     
    -   return (0);
    +   return 0;
     }
     
     png_uint_32 PNGAPI
    @@ -177,42 +176,41 @@ png_get_y_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp
         info_ptr)
     {
     #ifdef PNG_pHYs_SUPPORTED
    +   png_debug(1, "in png_get_y_pixels_per_meter");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_pHYs) != 0)
        {
    -      png_debug1(1, "in %s retrieval function",
    -          "png_get_y_pixels_per_meter");
    -
           if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER)
    -         return (info_ptr->y_pixels_per_unit);
    +         return info_ptr->y_pixels_per_unit;
        }
     #else
        PNG_UNUSED(png_ptr)
        PNG_UNUSED(info_ptr)
     #endif
     
    -   return (0);
    +   return 0;
     }
     
     png_uint_32 PNGAPI
     png_get_pixels_per_meter(png_const_structrp png_ptr, png_const_inforp info_ptr)
     {
     #ifdef PNG_pHYs_SUPPORTED
    +   png_debug(1, "in png_get_pixels_per_meter");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_pHYs) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "png_get_pixels_per_meter");
    -
           if (info_ptr->phys_unit_type == PNG_RESOLUTION_METER &&
               info_ptr->x_pixels_per_unit == info_ptr->y_pixels_per_unit)
    -         return (info_ptr->x_pixels_per_unit);
    +         return info_ptr->x_pixels_per_unit;
        }
     #else
        PNG_UNUSED(png_ptr)
        PNG_UNUSED(info_ptr)
     #endif
     
    -   return (0);
    +   return 0;
     }
     
     #ifdef PNG_FLOATING_POINT_SUPPORTED
    @@ -221,21 +219,21 @@ png_get_pixel_aspect_ratio(png_const_structrp png_ptr, png_const_inforp
        info_ptr)
     {
     #ifdef PNG_READ_pHYs_SUPPORTED
    +   png_debug(1, "in png_get_pixel_aspect_ratio");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_pHYs) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio");
    -
           if (info_ptr->x_pixels_per_unit != 0)
    -         return ((float)((float)info_ptr->y_pixels_per_unit
    -             /(float)info_ptr->x_pixels_per_unit));
    +         return (float)info_ptr->y_pixels_per_unit
    +              / (float)info_ptr->x_pixels_per_unit;
        }
     #else
        PNG_UNUSED(png_ptr)
        PNG_UNUSED(info_ptr)
     #endif
     
    -   return ((float)0.0);
    +   return (float)0.0;
     }
     #endif
     
    @@ -245,6 +243,8 @@ png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr,
         png_const_inforp info_ptr)
     {
     #ifdef PNG_READ_pHYs_SUPPORTED
    +   png_debug(1, "in png_get_pixel_aspect_ratio_fixed");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_pHYs) != 0 &&
            info_ptr->x_pixels_per_unit > 0 && info_ptr->y_pixels_per_unit > 0 &&
    @@ -253,8 +253,6 @@ png_get_pixel_aspect_ratio_fixed(png_const_structrp png_ptr,
        {
           png_fixed_point res;
     
    -      png_debug1(1, "in %s retrieval function", "png_get_aspect_ratio_fixed");
    -
           /* The following casts work because a PNG 4 byte integer only has a valid
            * range of 0..2^31-1; otherwise the cast might overflow.
            */
    @@ -275,80 +273,80 @@ png_int_32 PNGAPI
     png_get_x_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
     {
     #ifdef PNG_oFFs_SUPPORTED
    +   png_debug(1, "in png_get_x_offset_microns");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_oFFs) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "png_get_x_offset_microns");
    -
           if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
    -         return (info_ptr->x_offset);
    +         return info_ptr->x_offset;
        }
     #else
        PNG_UNUSED(png_ptr)
        PNG_UNUSED(info_ptr)
     #endif
     
    -   return (0);
    +   return 0;
     }
     
     png_int_32 PNGAPI
     png_get_y_offset_microns(png_const_structrp png_ptr, png_const_inforp info_ptr)
     {
     #ifdef PNG_oFFs_SUPPORTED
    +   png_debug(1, "in png_get_y_offset_microns");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_oFFs) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "png_get_y_offset_microns");
    -
           if (info_ptr->offset_unit_type == PNG_OFFSET_MICROMETER)
    -         return (info_ptr->y_offset);
    +         return info_ptr->y_offset;
        }
     #else
        PNG_UNUSED(png_ptr)
        PNG_UNUSED(info_ptr)
     #endif
     
    -   return (0);
    +   return 0;
     }
     
     png_int_32 PNGAPI
     png_get_x_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
     {
     #ifdef PNG_oFFs_SUPPORTED
    +   png_debug(1, "in png_get_x_offset_pixels");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_oFFs) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "png_get_x_offset_pixels");
    -
           if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
    -         return (info_ptr->x_offset);
    +         return info_ptr->x_offset;
        }
     #else
        PNG_UNUSED(png_ptr)
        PNG_UNUSED(info_ptr)
     #endif
     
    -   return (0);
    +   return 0;
     }
     
     png_int_32 PNGAPI
     png_get_y_offset_pixels(png_const_structrp png_ptr, png_const_inforp info_ptr)
     {
     #ifdef PNG_oFFs_SUPPORTED
    +   png_debug(1, "in png_get_y_offset_pixels");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_oFFs) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "png_get_y_offset_pixels");
    -
           if (info_ptr->offset_unit_type == PNG_OFFSET_PIXEL)
    -         return (info_ptr->y_offset);
    +         return info_ptr->y_offset;
        }
     #else
        PNG_UNUSED(png_ptr)
        PNG_UNUSED(info_ptr)
     #endif
     
    -   return (0);
    +   return 0;
     }
     
     #ifdef PNG_INCH_CONVERSIONS_SUPPORTED
    @@ -462,11 +460,11 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
     {
        png_uint_32 retval = 0;
     
    +   png_debug1(1, "in %s retrieval function", "pHYs");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_pHYs) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "pHYs");
    -
           if (res_x != NULL)
           {
              *res_x = info_ptr->x_pixels_per_unit;
    @@ -492,7 +490,7 @@ png_get_pHYs_dpi(png_const_structrp png_ptr, png_const_inforp info_ptr,
           }
        }
     
    -   return (retval);
    +   return retval;
     }
     #endif /* pHYs */
     #endif /* INCH_CONVERSIONS */
    @@ -506,9 +504,9 @@ png_byte PNGAPI
     png_get_channels(png_const_structrp png_ptr, png_const_inforp info_ptr)
     {
        if (png_ptr != NULL && info_ptr != NULL)
    -      return(info_ptr->channels);
    +      return info_ptr->channels;
     
    -   return (0);
    +   return 0;
     }
     
     #ifdef PNG_READ_SUPPORTED
    @@ -516,9 +514,9 @@ png_const_bytep PNGAPI
     png_get_signature(png_const_structrp png_ptr, png_const_inforp info_ptr)
     {
        if (png_ptr != NULL && info_ptr != NULL)
    -      return(info_ptr->signature);
    +      return info_ptr->signature;
     
    -   return (NULL);
    +   return NULL;
     }
     #endif
     
    @@ -527,17 +525,17 @@ png_uint_32 PNGAPI
     png_get_bKGD(png_const_structrp png_ptr, png_inforp info_ptr,
         png_color_16p *background)
     {
    +   png_debug1(1, "in %s retrieval function", "bKGD");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_bKGD) != 0 &&
            background != NULL)
        {
    -      png_debug1(1, "in %s retrieval function", "bKGD");
    -
           *background = &(info_ptr->background);
    -      return (PNG_INFO_bKGD);
    +      return PNG_INFO_bKGD;
        }
     
    -   return (0);
    +   return 0;
     }
     #endif
     
    @@ -552,6 +550,8 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
         double *white_x, double *white_y, double *red_x, double *red_y,
         double *green_x, double *green_y, double *blue_x, double *blue_y)
     {
    +   png_debug1(1, "in %s retrieval function", "cHRM");
    +
        /* Quiet API change: this code used to only return the end points if a cHRM
         * chunk was present, but the end points can also come from iCCP or sRGB
         * chunks, so in 1.6.0 the png_get_ APIs return the end points regardless and
    @@ -561,8 +561,6 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
        if (png_ptr != NULL && info_ptr != NULL &&
           (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "cHRM");
    -
           if (white_x != NULL)
              *white_x = png_float(png_ptr,
                  info_ptr->colorspace.end_points_xy.whitex, "cHRM white X");
    @@ -587,10 +585,10 @@ png_get_cHRM(png_const_structrp png_ptr, png_const_inforp info_ptr,
           if (blue_y != NULL)
              *blue_y = png_float(png_ptr, info_ptr->colorspace.end_points_xy.bluey,
                  "cHRM blue Y");
    -      return (PNG_INFO_cHRM);
    +      return PNG_INFO_cHRM;
        }
     
    -   return (0);
    +   return 0;
     }
     
     png_uint_32 PNGAPI
    @@ -599,11 +597,11 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
         double *green_Y, double *green_Z, double *blue_X, double *blue_Y,
         double *blue_Z)
     {
    +   png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "cHRM_XYZ(float)");
    -
           if (red_X != NULL)
              *red_X = png_float(png_ptr, info_ptr->colorspace.end_points_XYZ.red_X,
                  "cHRM red X");
    @@ -631,10 +629,10 @@ png_get_cHRM_XYZ(png_const_structrp png_ptr, png_const_inforp info_ptr,
           if (blue_Z != NULL)
              *blue_Z = png_float(png_ptr,
                  info_ptr->colorspace.end_points_XYZ.blue_Z, "cHRM blue Z");
    -      return (PNG_INFO_cHRM);
    +      return PNG_INFO_cHRM;
        }
     
    -   return (0);
    +   return 0;
     }
     #  endif
     
    @@ -647,11 +645,11 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
         png_fixed_point *int_blue_X, png_fixed_point *int_blue_Y,
         png_fixed_point *int_blue_Z)
     {
    +   png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
           (info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "cHRM_XYZ");
    -
           if (int_red_X != NULL)
              *int_red_X = info_ptr->colorspace.end_points_XYZ.red_X;
           if (int_red_Y != NULL)
    @@ -670,10 +668,10 @@ png_get_cHRM_XYZ_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
              *int_blue_Y = info_ptr->colorspace.end_points_XYZ.blue_Y;
           if (int_blue_Z != NULL)
              *int_blue_Z = info_ptr->colorspace.end_points_XYZ.blue_Z;
    -      return (PNG_INFO_cHRM);
    +      return PNG_INFO_cHRM;
        }
     
    -   return (0);
    +   return 0;
     }
     
     png_uint_32 PNGAPI
    @@ -703,10 +701,10 @@ png_get_cHRM_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
              *blue_x = info_ptr->colorspace.end_points_xy.bluex;
           if (blue_y != NULL)
              *blue_y = info_ptr->colorspace.end_points_xy.bluey;
    -      return (PNG_INFO_cHRM);
    +      return PNG_INFO_cHRM;
        }
     
    -   return (0);
    +   return 0;
     }
     #  endif
     #endif
    @@ -724,10 +722,10 @@ png_get_gAMA_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
            file_gamma != NULL)
        {
           *file_gamma = info_ptr->colorspace.gamma;
    -      return (PNG_INFO_gAMA);
    +      return PNG_INFO_gAMA;
        }
     
    -   return (0);
    +   return 0;
     }
     #  endif
     
    @@ -744,10 +742,10 @@ png_get_gAMA(png_const_structrp png_ptr, png_const_inforp info_ptr,
        {
           *file_gamma = png_float(png_ptr, info_ptr->colorspace.gamma,
               "png_get_gAMA");
    -      return (PNG_INFO_gAMA);
    +      return PNG_INFO_gAMA;
        }
     
    -   return (0);
    +   return 0;
     }
     #  endif
     #endif
    @@ -763,10 +761,10 @@ png_get_sRGB(png_const_structrp png_ptr, png_const_inforp info_ptr,
           (info_ptr->valid & PNG_INFO_sRGB) != 0 && file_srgb_intent != NULL)
        {
           *file_srgb_intent = info_ptr->colorspace.rendering_intent;
    -      return (PNG_INFO_sRGB);
    +      return PNG_INFO_sRGB;
        }
     
    -   return (0);
    +   return 0;
     }
     #endif
     
    @@ -790,10 +788,10 @@ png_get_iCCP(png_const_structrp png_ptr, png_inforp info_ptr,
            */
           if (compression_type != NULL)
              *compression_type = PNG_COMPRESSION_TYPE_BASE;
    -      return (PNG_INFO_iCCP);
    +      return PNG_INFO_iCCP;
        }
     
    -   return (0);
    +   return 0;
     
     }
     #endif
    @@ -803,13 +801,15 @@ int PNGAPI
     png_get_sPLT(png_const_structrp png_ptr, png_inforp info_ptr,
         png_sPLT_tpp spalettes)
     {
    +   png_debug1(1, "in %s retrieval function", "sPLT");
    +
        if (png_ptr != NULL && info_ptr != NULL && spalettes != NULL)
        {
           *spalettes = info_ptr->splt_palettes;
           return info_ptr->splt_palettes_num;
        }
     
    -   return (0);
    +   return 0;
     }
     #endif
     
    @@ -835,10 +835,10 @@ png_get_eXIf_1(png_const_structrp png_ptr, png_const_inforp info_ptr,
        {
           *num_exif = info_ptr->num_exif;
           *exif = info_ptr->exif;
    -      return (PNG_INFO_eXIf);
    +      return PNG_INFO_eXIf;
        }
     
    -   return (0);
    +   return 0;
     }
     #endif
     
    @@ -853,10 +853,10 @@ png_get_hIST(png_const_structrp png_ptr, png_inforp info_ptr,
            (info_ptr->valid & PNG_INFO_hIST) != 0 && hist != NULL)
        {
           *hist = info_ptr->hist;
    -      return (PNG_INFO_hIST);
    +      return PNG_INFO_hIST;
        }
     
    -   return (0);
    +   return 0;
     }
     #endif
     
    @@ -869,7 +869,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
        png_debug1(1, "in %s retrieval function", "IHDR");
     
        if (png_ptr == NULL || info_ptr == NULL)
    -      return (0);
    +      return 0;
     
        if (width != NULL)
            *width = info_ptr->width;
    @@ -901,7 +901,7 @@ png_get_IHDR(png_const_structrp png_ptr, png_const_inforp info_ptr,
            info_ptr->bit_depth, info_ptr->color_type, info_ptr->interlace_type,
            info_ptr->compression_type, info_ptr->filter_type);
     
    -   return (1);
    +   return 1;
     }
     
     #ifdef PNG_oFFs_SUPPORTED
    @@ -918,10 +918,10 @@ png_get_oFFs(png_const_structrp png_ptr, png_const_inforp info_ptr,
           *offset_x = info_ptr->x_offset;
           *offset_y = info_ptr->y_offset;
           *unit_type = (int)info_ptr->offset_unit_type;
    -      return (PNG_INFO_oFFs);
    +      return PNG_INFO_oFFs;
        }
     
    -   return (0);
    +   return 0;
     }
     #endif
     
    @@ -945,10 +945,10 @@ png_get_pCAL(png_const_structrp png_ptr, png_inforp info_ptr,
           *nparams = (int)info_ptr->pcal_nparams;
           *units = info_ptr->pcal_units;
           *params = info_ptr->pcal_params;
    -      return (PNG_INFO_pCAL);
    +      return PNG_INFO_pCAL;
        }
     
    -   return (0);
    +   return 0;
     }
     #endif
     
    @@ -960,6 +960,8 @@ png_uint_32 PNGAPI
     png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
         int *unit, png_fixed_point *width, png_fixed_point *height)
     {
    +   png_debug1(1, "in %s retrieval function", "sCAL");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_sCAL) != 0)
        {
    @@ -971,10 +973,10 @@ png_get_sCAL_fixed(png_const_structrp png_ptr, png_const_inforp info_ptr,
           *width = png_fixed(png_ptr, atof(info_ptr->scal_s_width), "sCAL width");
           *height = png_fixed(png_ptr, atof(info_ptr->scal_s_height),
               "sCAL height");
    -      return (PNG_INFO_sCAL);
    +      return PNG_INFO_sCAL;
        }
     
    -   return(0);
    +   return 0;
     }
     #    endif /* FLOATING_ARITHMETIC */
     #  endif /* FIXED_POINT */
    @@ -983,32 +985,36 @@ png_uint_32 PNGAPI
     png_get_sCAL(png_const_structrp png_ptr, png_const_inforp info_ptr,
         int *unit, double *width, double *height)
     {
    +   png_debug1(1, "in %s retrieval function", "sCAL(float)");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_sCAL) != 0)
        {
           *unit = info_ptr->scal_unit;
           *width = atof(info_ptr->scal_s_width);
           *height = atof(info_ptr->scal_s_height);
    -      return (PNG_INFO_sCAL);
    +      return PNG_INFO_sCAL;
        }
     
    -   return(0);
    +   return 0;
     }
     #  endif /* FLOATING POINT */
     png_uint_32 PNGAPI
     png_get_sCAL_s(png_const_structrp png_ptr, png_const_inforp info_ptr,
         int *unit, png_charpp width, png_charpp height)
     {
    +   png_debug1(1, "in %s retrieval function", "sCAL(str)");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_sCAL) != 0)
        {
           *unit = info_ptr->scal_unit;
           *width = info_ptr->scal_s_width;
           *height = info_ptr->scal_s_height;
    -      return (PNG_INFO_sCAL);
    +      return PNG_INFO_sCAL;
        }
     
    -   return(0);
    +   return 0;
     }
     #endif /* sCAL */
     
    @@ -1043,7 +1049,7 @@ png_get_pHYs(png_const_structrp png_ptr, png_const_inforp info_ptr,
           }
        }
     
    -   return (retval);
    +   return retval;
     }
     #endif /* pHYs */
     
    @@ -1059,10 +1065,10 @@ png_get_PLTE(png_const_structrp png_ptr, png_inforp info_ptr,
           *palette = info_ptr->palette;
           *num_palette = info_ptr->num_palette;
           png_debug1(3, "num_palette = %d", *num_palette);
    -      return (PNG_INFO_PLTE);
    +      return PNG_INFO_PLTE;
        }
     
    -   return (0);
    +   return 0;
     }
     
     #ifdef PNG_sBIT_SUPPORTED
    @@ -1076,10 +1082,10 @@ png_get_sBIT(png_const_structrp png_ptr, png_inforp info_ptr,
            (info_ptr->valid & PNG_INFO_sBIT) != 0 && sig_bit != NULL)
        {
           *sig_bit = &(info_ptr->sig_bit);
    -      return (PNG_INFO_sBIT);
    +      return PNG_INFO_sBIT;
        }
     
    -   return (0);
    +   return 0;
     }
     #endif
     
    @@ -1090,7 +1096,7 @@ png_get_text(png_const_structrp png_ptr, png_inforp info_ptr,
     {
        if (png_ptr != NULL && info_ptr != NULL && info_ptr->num_text > 0)
        {
    -      png_debug1(1, "in 0x%lx retrieval function",
    +      png_debug1(1, "in text retrieval function, chunk typeid = 0x%lx",
              (unsigned long)png_ptr->chunk_name);
     
           if (text_ptr != NULL)
    @@ -1105,7 +1111,7 @@ png_get_text(png_const_structrp png_ptr, png_inforp info_ptr,
        if (num_text != NULL)
           *num_text = 0;
     
    -   return(0);
    +   return 0;
     }
     #endif
     
    @@ -1120,10 +1126,10 @@ png_get_tIME(png_const_structrp png_ptr, png_inforp info_ptr,
            (info_ptr->valid & PNG_INFO_tIME) != 0 && mod_time != NULL)
        {
           *mod_time = &(info_ptr->mod_time);
    -      return (PNG_INFO_tIME);
    +      return PNG_INFO_tIME;
        }
     
    -   return (0);
    +   return 0;
     }
     #endif
     
    @@ -1133,11 +1139,12 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
         png_bytep *trans_alpha, int *num_trans, png_color_16p *trans_color)
     {
        png_uint_32 retval = 0;
    +
    +   png_debug1(1, "in %s retrieval function", "tRNS");
    +
        if (png_ptr != NULL && info_ptr != NULL &&
            (info_ptr->valid & PNG_INFO_tRNS) != 0)
        {
    -      png_debug1(1, "in %s retrieval function", "tRNS");
    -
           if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE)
           {
              if (trans_alpha != NULL)
    @@ -1169,7 +1176,7 @@ png_get_tRNS(png_const_structrp png_ptr, png_inforp info_ptr,
           }
        }
     
    -   return (retval);
    +   return retval;
     }
     #endif
     
    @@ -1184,7 +1191,7 @@ png_get_unknown_chunks(png_const_structrp png_ptr, png_inforp info_ptr,
           return info_ptr->unknown_chunks_num;
        }
     
    -   return (0);
    +   return 0;
     }
     #endif
     
    @@ -1280,7 +1287,7 @@ png_get_palette_max(png_const_structp png_ptr, png_const_infop info_ptr)
        if (png_ptr != NULL && info_ptr != NULL)
           return png_ptr->num_palette_max;
     
    -   return (-1);
    +   return -1;
     }
     #  endif
     #endif
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
    index 90fea5c8f21..e78933bacf2 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pnglibconf.h
    @@ -31,7 +31,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      */
    -/* libpng version 1.6.40 */
    +/* libpng version 1.6.43 */
     
     /* Copyright (c) 2018-2023 Cosmin Truta */
     /* Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson */
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
    index a98b2013256..816631cae18 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpread.c
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * Copyright (c) 2018 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -173,10 +173,10 @@ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr)
            num_to_check);
        png_ptr->sig_bytes = (png_byte)(png_ptr->sig_bytes + num_to_check);
     
    -   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check))
    +   if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
        {
           if (num_checked < 4 &&
    -          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
    +          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0)
              png_error(png_ptr, "Not a PNG file");
     
           else
    @@ -322,6 +322,14 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr)
           png_handle_cHRM(png_ptr, info_ptr, png_ptr->push_length);
        }
     
    +#endif
    +#ifdef PNG_READ_eXIf_SUPPORTED
    +   else if (png_ptr->chunk_name == png_eXIf)
    +   {
    +      PNG_PUSH_SAVE_BUFFER_IF_FULL
    +      png_handle_eXIf(png_ptr, info_ptr, png_ptr->push_length);
    +   }
    +
     #endif
     #ifdef PNG_READ_sRGB_SUPPORTED
        else if (chunk_name == png_sRGB)
    @@ -1117,7 +1125,7 @@ png_voidp PNGAPI
     png_get_progressive_ptr(png_const_structrp png_ptr)
     {
        if (png_ptr == NULL)
    -      return (NULL);
    +      return NULL;
     
        return png_ptr->io_ptr;
     }
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
    index 914d0b97b1d..18424542b00 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngpriv.h
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * Copyright (c) 2018-2023 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -64,7 +64,7 @@
      * still required (as of 2011-05-02.)
      */
     #ifndef _POSIX_SOURCE
    -# define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
    +#  define _POSIX_SOURCE 1 /* Just the POSIX 1003.1 and C89 APIs */
     #endif
     
     #ifndef PNG_VERSION_INFO_ONLY
    @@ -218,13 +218,27 @@
     #endif /* PNG_ARM_NEON_OPT > 0 */
     
     #ifndef PNG_MIPS_MSA_OPT
    -#  if defined(__mips_msa) && (__mips_isa_rev >= 5) && defined(PNG_ALIGNED_MEMORY_SUPPORTED)
    +#  if defined(__mips_msa) && (__mips_isa_rev >= 5) && \
    +   defined(PNG_ALIGNED_MEMORY_SUPPORTED)
     #     define PNG_MIPS_MSA_OPT 2
     #  else
     #     define PNG_MIPS_MSA_OPT 0
     #  endif
     #endif
     
    +#ifndef PNG_MIPS_MMI_OPT
    +#  ifdef PNG_MIPS_MMI
    +#    if defined(__mips_loongson_mmi) && (_MIPS_SIM == _ABI64) && \
    +     defined(PNG_ALIGNED_MEMORY_SUPPORTED)
    +#       define PNG_MIPS_MMI_OPT 1
    +#    else
    +#       define PNG_MIPS_MMI_OPT 0
    +#    endif
    +#  else
    +#    define PNG_MIPS_MMI_OPT 0
    +#  endif
    +#endif
    +
     #ifndef PNG_POWERPC_VSX_OPT
     #  if defined(__PPC64__) && defined(__ALTIVEC__) && defined(__VSX__)
     #     define PNG_POWERPC_VSX_OPT 2
    @@ -233,13 +247,21 @@
     #  endif
     #endif
     
    +#ifndef PNG_LOONGARCH_LSX_OPT
    +#  if defined(__loongarch_sx)
    +#     define PNG_LOONGARCH_LSX_OPT 1
    +#  else
    +#     define PNG_LOONGARCH_LSX_OPT 0
    +#  endif
    +#endif
    +
     #ifndef PNG_INTEL_SSE_OPT
     #   ifdef PNG_INTEL_SSE
           /* Only check for SSE if the build configuration has been modified to
            * enable SSE optimizations.  This means that these optimizations will
            * be off by default.  See contrib/intel for more details.
            */
    -#     if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
    +#      if defined(__SSE4_1__) || defined(__AVX__) || defined(__SSSE3__) || \
            defined(__SSE2__) || defined(_M_X64) || defined(_M_AMD64) || \
            (defined(_M_IX86_FP) && _M_IX86_FP >= 2)
     #         define PNG_INTEL_SSE_OPT 1
    @@ -276,7 +298,6 @@
     #endif
     
     #if PNG_MIPS_MSA_OPT > 0
    -#  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_msa
     #  ifndef PNG_MIPS_MSA_IMPLEMENTATION
     #     if defined(__mips_msa)
     #        if defined(__clang__)
    @@ -292,11 +313,28 @@
     
     #  ifndef PNG_MIPS_MSA_IMPLEMENTATION
     #     define PNG_MIPS_MSA_IMPLEMENTATION 1
    +#     define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_mips
     #  endif
     #else
     #  define PNG_MIPS_MSA_IMPLEMENTATION 0
     #endif /* PNG_MIPS_MSA_OPT > 0 */
     
    +#if PNG_MIPS_MMI_OPT > 0
    +#  ifndef PNG_MIPS_MMI_IMPLEMENTATION
    +#     if defined(__mips_loongson_mmi) && (_MIPS_SIM == _ABI64)
    +#        define PNG_MIPS_MMI_IMPLEMENTATION 2
    +#     else /* !defined __mips_loongson_mmi  || _MIPS_SIM != _ABI64 */
    +#        define PNG_MIPS_MMI_IMPLEMENTATION 0
    +#     endif /* __mips_loongson_mmi  && _MIPS_SIM == _ABI64 */
    +#  endif /* !PNG_MIPS_MMI_IMPLEMENTATION */
    +
    +#   if PNG_MIPS_MMI_IMPLEMENTATION > 0
    +#      define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_mips
    +#   endif
    +#else
    +#   define PNG_MIPS_MMI_IMPLEMENTATION 0
    +#endif /* PNG_MIPS_MMI_OPT > 0 */
    +
     #if PNG_POWERPC_VSX_OPT > 0
     #  define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_vsx
     #  define PNG_POWERPC_VSX_IMPLEMENTATION 1
    @@ -304,6 +342,12 @@
     #  define PNG_POWERPC_VSX_IMPLEMENTATION 0
     #endif
     
    +#if PNG_LOONGARCH_LSX_OPT > 0
    +#   define PNG_FILTER_OPTIMIZATIONS png_init_filter_functions_lsx
    +#   define PNG_LOONGARCH_LSX_IMPLEMENTATION 1
    +#else
    +#   define PNG_LOONGARCH_LSX_IMPLEMENTATION 0
    +#endif
     
     /* Is this a build of a DLL where compilation of the object modules requires
      * different preprocessor settings to those required for a simple library?  If
    @@ -542,18 +586,8 @@
         */
     #  include 
     
    -#  if (defined(__MWERKS__) && defined(macintosh)) || defined(applec) || \
    -    defined(THINK_C) || defined(__SC__) || defined(TARGET_OS_MAC)
    -   /* We need to check that  hasn't already been included earlier
    -    * as it seems it doesn't agree with , yet we should really use
    -    *  if possible.
    -    */
    -#    if !defined(__MATH_H__) && !defined(__MATH_H) && !defined(__cmath__)
    -#      include 
    -#    endif
    -#  else
    -#    include 
    -#  endif
    +#  include 
    +
     #  if defined(_AMIGA) && defined(__SASC) && defined(_M68881)
        /* Amiga SAS/C: We must include builtin FPU functions when compiling using
         * MATH=68881
    @@ -1334,7 +1368,7 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_neon,(png_row_infop
         row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
     #endif
     
    -#if PNG_MIPS_MSA_OPT > 0
    +#if PNG_MIPS_MSA_IMPLEMENTATION == 1
     PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_msa,(png_row_infop row_info,
         png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
     PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_msa,(png_row_infop
    @@ -1351,6 +1385,23 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_msa,(png_row_infop
         row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
     #endif
     
    +#if PNG_MIPS_MMI_IMPLEMENTATION > 0
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_mmi,(png_row_infop row_info,
    +    png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_mmi,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_mmi,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_mmi,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_mmi,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_mmi,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_mmi,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +#endif
    +
     #if PNG_POWERPC_VSX_OPT > 0
     PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_vsx,(png_row_infop row_info,
         png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    @@ -1383,6 +1434,23 @@ PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_sse2,(png_row_infop
         row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
     #endif
     
    +#if PNG_LOONGARCH_LSX_IMPLEMENTATION == 1
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_up_lsx,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub3_lsx,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_sub4_lsx,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg3_lsx,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_avg4_lsx,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth3_lsx,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +PNG_INTERNAL_FUNCTION(void,png_read_filter_row_paeth4_lsx,(png_row_infop
    +    row_info, png_bytep row, png_const_bytep prev_row),PNG_EMPTY);
    +#endif
    +
     /* Choose the best filter to use and filter the row data */
     PNG_INTERNAL_FUNCTION(void,png_write_find_filter,(png_structrp png_ptr,
         png_row_infop row_info),PNG_EMPTY);
    @@ -2122,17 +2190,27 @@ PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_neon,
        (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
     #endif
     
    -#if PNG_MIPS_MSA_OPT > 0
    -PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_msa,
    +#if PNG_MIPS_MSA_IMPLEMENTATION == 1
    +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_mips,
        (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
     #endif
     
    +#  if PNG_MIPS_MMI_IMPLEMENTATION > 0
    +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_mips,
    +   (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
    +#  endif
    +
     #  if PNG_INTEL_SSE_IMPLEMENTATION > 0
     PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_sse2,
        (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
     #  endif
     #endif
     
    +#if PNG_LOONGARCH_LSX_OPT > 0
    +PNG_INTERNAL_FUNCTION(void, png_init_filter_functions_lsx,
    +    (png_structp png_ptr, unsigned int bpp), PNG_EMPTY);
    +#endif
    +
     PNG_INTERNAL_FUNCTION(png_uint_32, png_check_keyword, (png_structrp png_ptr,
        png_const_charp key, png_bytep new_key), PNG_EMPTY);
     
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
    index 3631e60f36b..e9e94477545 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngread.c
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * Copyright (c) 2018-2019 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -596,7 +596,11 @@ png_read_row(png_structrp png_ptr, png_bytep row, png_bytep dsp_row)
     #endif
     
     #ifdef PNG_READ_TRANSFORMS_SUPPORTED
    -   if (png_ptr->transformations)
    +   if (png_ptr->transformations
    +#     ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED
    +         || png_ptr->num_palette_max >= 0
    +#     endif
    +      )
           png_do_read_transformations(png_ptr, &row_info);
     #endif
     
    @@ -813,7 +817,7 @@ png_read_end(png_structrp png_ptr, png_inforp info_ptr)
     #ifdef PNG_READ_CHECK_FOR_INVALID_INDEX_SUPPORTED
        /* Report invalid palette index; added at libng-1.5.10 */
        if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE &&
    -       png_ptr->num_palette_max > png_ptr->num_palette)
    +       png_ptr->num_palette_max >= png_ptr->num_palette)
           png_benign_error(png_ptr, "Read palette index exceeding num_palette");
     #endif
     
    @@ -1077,6 +1081,8 @@ void PNGAPI
     png_read_png(png_structrp png_ptr, png_inforp info_ptr,
         int transforms, voidp params)
     {
    +   png_debug(1, "in png_read_png");
    +
        if (png_ptr == NULL || info_ptr == NULL)
           return;
     
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
    index 843eb5fff2a..a393de4b79d 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrtran.c
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * Copyright (c) 2018-2019 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -318,21 +318,20 @@ png_set_alpha_mode_fixed(png_structrp png_ptr, int mode,
        int compose = 0;
        png_fixed_point file_gamma;
     
    -   png_debug(1, "in png_set_alpha_mode");
    +   png_debug(1, "in png_set_alpha_mode_fixed");
     
        if (png_rtran_ok(png_ptr, 0) == 0)
           return;
     
        output_gamma = translate_gamma_flags(png_ptr, output_gamma, 1/*screen*/);
     
    -   /* Validate the value to ensure it is in a reasonable range. The value
    +   /* Validate the value to ensure it is in a reasonable range.  The value
         * is expected to be 1 or greater, but this range test allows for some
    -    * viewing correction values.  The intent is to weed out users of this API
    -    * who use the inverse of the gamma value accidentally!  Since some of these
    -    * values are reasonable this may have to be changed:
    +    * viewing correction values.  The intent is to weed out the API users
    +    * who might use the inverse of the gamma value accidentally!
         *
    -    * 1.6.x: changed from 0.07..3 to 0.01..100 (to accommodate the optimal 16-bit
    -    * gamma of 36, and its reciprocal.)
    +    * In libpng 1.6.0, we changed from 0.07..3 to 0.01..100, to accommodate
    +    * the optimal 16-bit gamma of 36 and its reciprocal.
         */
        if (output_gamma < 1000 || output_gamma > 10000000)
           png_error(png_ptr, "output gamma out of expected range");
    @@ -469,7 +468,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
           int i;
     
           png_ptr->quantize_index = (png_bytep)png_malloc(png_ptr,
    -          (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
    +          (png_alloc_size_t)num_palette);
           for (i = 0; i < num_palette; i++)
              png_ptr->quantize_index[i] = (png_byte)i;
        }
    @@ -486,7 +485,7 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
     
              /* Initialize an array to sort colors */
              png_ptr->quantize_sort = (png_bytep)png_malloc(png_ptr,
    -             (png_alloc_size_t)((png_uint_32)num_palette * (sizeof (png_byte))));
    +             (png_alloc_size_t)num_palette);
     
              /* Initialize the quantize_sort array */
              for (i = 0; i < num_palette; i++)
    @@ -620,11 +619,9 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
     
              /* Initialize palette index arrays */
              png_ptr->index_to_palette = (png_bytep)png_malloc(png_ptr,
    -             (png_alloc_size_t)((png_uint_32)num_palette *
    -             (sizeof (png_byte))));
    +             (png_alloc_size_t)num_palette);
              png_ptr->palette_to_index = (png_bytep)png_malloc(png_ptr,
    -             (png_alloc_size_t)((png_uint_32)num_palette *
    -             (sizeof (png_byte))));
    +             (png_alloc_size_t)num_palette);
     
              /* Initialize the sort array */
              for (i = 0; i < num_palette; i++)
    @@ -789,12 +786,11 @@ png_set_quantize(png_structrp png_ptr, png_colorp palette,
           size_t num_entries = ((size_t)1 << total_bits);
     
           png_ptr->palette_lookup = (png_bytep)png_calloc(png_ptr,
    -          (png_alloc_size_t)(num_entries * (sizeof (png_byte))));
    +          (png_alloc_size_t)(num_entries));
     
    -      distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)(num_entries *
    -          (sizeof (png_byte))));
    +      distance = (png_bytep)png_malloc(png_ptr, (png_alloc_size_t)num_entries);
     
    -      memset(distance, 0xff, num_entries * (sizeof (png_byte)));
    +      memset(distance, 0xff, num_entries);
     
           for (i = 0; i < num_palette; i++)
           {
    @@ -998,7 +994,7 @@ void PNGFAPI
     png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action,
         png_fixed_point red, png_fixed_point green)
     {
    -   png_debug(1, "in png_set_rgb_to_gray");
    +   png_debug(1, "in png_set_rgb_to_gray_fixed");
     
        /* Need the IHDR here because of the check on color_type below. */
        /* TODO: fix this */
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
    index 524297c5a10..5280140d12b 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngrutil.c
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * Copyright (c) 2018-2022 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -54,7 +54,7 @@ png_get_uint_31(png_const_structrp png_ptr, png_const_bytep buf)
        if (uval > PNG_UINT_31_MAX)
           png_error(png_ptr, "PNG unsigned integer out of range");
     
    -   return (uval);
    +   return uval;
     }
     
     #if defined(PNG_READ_gAMA_SUPPORTED) || defined(PNG_READ_cHRM_SUPPORTED)
    @@ -168,7 +168,7 @@ png_read_sig(png_structrp png_ptr, png_inforp info_ptr)
        if (png_sig_cmp(info_ptr->signature, num_checked, num_to_check) != 0)
        {
           if (num_checked < 4 &&
    -          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4))
    +          png_sig_cmp(info_ptr->signature, num_checked, num_to_check - 4) != 0)
              png_error(png_ptr, "Not a PNG file");
           else
              png_error(png_ptr, "PNG file corrupted by ASCII conversion");
    @@ -199,7 +199,7 @@ png_read_chunk_header(png_structrp png_ptr)
        /* Put the chunk name into png_ptr->chunk_name. */
        png_ptr->chunk_name = PNG_CHUNK_FROM_STRING(buf+4);
     
    -   png_debug2(0, "Reading %lx chunk, length = %lu",
    +   png_debug2(0, "Reading chunk typeid = 0x%lx, length = %lu",
            (unsigned long)png_ptr->chunk_name, (unsigned long)length);
     
        /* Reset the crc and run it over the chunk name. */
    @@ -266,10 +266,10 @@ png_crc_finish(png_structrp png_ptr, png_uint_32 skip)
           else
              png_chunk_error(png_ptr, "CRC error");
     
    -      return (1);
    +      return 1;
        }
     
    -   return (0);
    +   return 0;
     }
     
     /* Compare the CRC stored in the PNG file with that calculated by libpng from
    @@ -305,11 +305,11 @@ png_crc_error(png_structrp png_ptr)
        if (need_crc != 0)
        {
           crc = png_get_uint_32(crc_bytes);
    -      return ((int)(crc != png_ptr->crc));
    +      return crc != png_ptr->crc;
        }
     
        else
    -      return (0);
    +      return 0;
     }
     
     #if defined(PNG_READ_iCCP_SUPPORTED) || defined(PNG_READ_iTXt_SUPPORTED) ||\
    @@ -449,8 +449,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner)
                 png_ptr->flags |= PNG_FLAG_ZSTREAM_INITIALIZED;
           }
     
    -#if ZLIB_VERNUM >= 0x1290 && \
    -   defined(PNG_SET_OPTION_SUPPORTED) && defined(PNG_IGNORE_ADLER32)
    +#ifdef PNG_DISABLE_ADLER32_CHECK_SUPPORTED
           if (((png_ptr->options >> PNG_IGNORE_ADLER32) & 3) == PNG_OPTION_ON)
              /* Turn off validation of the ADLER32 checksum in IDAT chunks */
              ret = inflateValidate(&png_ptr->zstream, 0);
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
    index 62612a02278..f53ab6fa1d1 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngset.c
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * Copyright (c) 2018-2023 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -791,11 +791,11 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
     {
        int i;
     
    -   png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U :
    -      (unsigned long)png_ptr->chunk_name);
    +   png_debug1(1, "in text storage function, chunk typeid = 0x%lx",
    +      png_ptr == NULL ? 0xabadca11UL : (unsigned long)png_ptr->chunk_name);
     
        if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL)
    -      return(0);
    +      return 0;
     
        /* Make sure we have enough space in the "text" array in info_struct
         * to hold all of the incoming text_ptr objects.  This compare can't overflow
    @@ -975,7 +975,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr,
           png_debug1(3, "transferred text chunk %d", info_ptr->num_text);
        }
     
    -   return(0);
    +   return 0;
     }
     #endif
     
    @@ -1091,6 +1091,8 @@ png_set_sPLT(png_const_structrp png_ptr,
     {
        png_sPLT_tp np;
     
    +   png_debug1(1, "in %s storage function", "sPLT");
    +
        if (png_ptr == NULL || info_ptr == NULL || nentries <= 0 || entries == NULL)
           return;
     
    @@ -1565,7 +1567,7 @@ void PNGAPI
     png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
         png_bytepp row_pointers)
     {
    -   png_debug1(1, "in %s storage function", "rows");
    +   png_debug(1, "in png_set_rows");
     
        if (png_ptr == NULL || info_ptr == NULL)
           return;
    @@ -1584,6 +1586,8 @@ png_set_rows(png_const_structrp png_ptr, png_inforp info_ptr,
     void PNGAPI
     png_set_compression_buffer_size(png_structrp png_ptr, size_t size)
     {
    +   png_debug(1, "in png_set_compression_buffer_size");
    +
        if (png_ptr == NULL)
           return;
     
    @@ -1655,6 +1659,8 @@ void PNGAPI
     png_set_user_limits(png_structrp png_ptr, png_uint_32 user_width_max,
         png_uint_32 user_height_max)
     {
    +   png_debug(1, "in png_set_user_limits");
    +
        /* Images with dimensions larger than these limits will be
         * rejected by png_set_IHDR().  To accept any PNG datastream
         * regardless of dimensions, set both limits to 0x7fffffff.
    @@ -1670,6 +1676,8 @@ png_set_user_limits(png_structrp png_ptr, png_uint_32 user_width_max,
     void PNGAPI
     png_set_chunk_cache_max(png_structrp png_ptr, png_uint_32 user_chunk_cache_max)
     {
    +   png_debug(1, "in png_set_chunk_cache_max");
    +
        if (png_ptr != NULL)
           png_ptr->user_chunk_cache_max = user_chunk_cache_max;
     }
    @@ -1679,6 +1687,8 @@ void PNGAPI
     png_set_chunk_malloc_max(png_structrp png_ptr,
         png_alloc_size_t user_chunk_malloc_max)
     {
    +   png_debug(1, "in png_set_chunk_malloc_max");
    +
        if (png_ptr != NULL)
           png_ptr->user_chunk_malloc_max = user_chunk_malloc_max;
     }
    diff --git a/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c b/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
    index 89a62191b6f..2350057e70e 100644
    --- a/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
    +++ b/src/java.desktop/share/native/libsplashscreen/libpng/pngtrans.c
    @@ -29,7 +29,7 @@
      * However, the following notice accompanied the original version of this
      * file and, per its terms, should not be removed:
      *
    - * Copyright (c) 2018 Cosmin Truta
    + * Copyright (c) 2018-2024 Cosmin Truta
      * Copyright (c) 1998-2002,2004,2006-2018 Glenn Randers-Pehrson
      * Copyright (c) 1996-1997 Andreas Dilger
      * Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc.
    @@ -131,10 +131,10 @@ png_set_interlace_handling(png_structrp png_ptr)
        if (png_ptr != 0 && png_ptr->interlaced != 0)
        {
           png_ptr->transformations |= PNG_INTERLACE;
    -      return (7);
    +      return 7;
        }
     
    -   return (1);
    +   return 1;
     }
     #endif
     
    @@ -526,6 +526,8 @@ png_do_strip_channel(png_row_infop row_info, png_bytep row, int at_start)
        png_bytep dp = row; /* destination pointer */
        png_bytep ep = row + row_info->rowbytes; /* One beyond end of row */
     
    +   png_debug(1, "in png_do_strip_channel");
    +
        /* At the start sp will point to the first byte to copy and dp to where
         * it is copied to.  ep always points just beyond the end of the row, so
         * the loop simply copies (channels-1) channels until sp reaches ep.
    @@ -726,6 +728,8 @@ png_do_bgr(png_row_infop row_info, png_bytep row)
     void /* PRIVATE */
     png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
     {
    +   png_debug(1, "in png_do_check_palette_indexes");
    +
        if (png_ptr->num_palette < (1 << row_info->bit_depth) &&
           png_ptr->num_palette > 0) /* num_palette can be 0 in MNG files */
        {
    @@ -736,7 +740,7 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info)
            * forms produced on either GCC or MSVC.
            */
           int padding = PNG_PADBITS(row_info->pixel_depth, row_info->width);
    -      png_bytep rp = png_ptr->row_buf + row_info->rowbytes - 1;
    +      png_bytep rp = png_ptr->row_buf + row_info->rowbytes;
     
           switch (row_info->bit_depth)
           {
    @@ -861,7 +865,7 @@ png_voidp PNGAPI
     png_get_user_transform_ptr(png_const_structrp png_ptr)
     {
        if (png_ptr == NULL)
    -      return (NULL);
    +      return NULL;
     
        return png_ptr->user_transform_ptr;
     }
    diff --git a/src/java.desktop/unix/classes/sun/awt/X11/XWM.java b/src/java.desktop/unix/classes/sun/awt/X11/XWM.java
    index 974888986ef..2330db90587 100644
    --- a/src/java.desktop/unix/classes/sun/awt/X11/XWM.java
    +++ b/src/java.desktop/unix/classes/sun/awt/X11/XWM.java
    @@ -1369,6 +1369,9 @@ Insets guessInsets(XDecoratedPeer window) {
                   case UNITY_COMPIZ_WM:
                       res = new Insets(28, 1, 1, 1);
                       break;
    +              case MUTTER_WM:
    +                  res = new Insets(37, 0, 0, 0);
    +                  break;
                   case MOTIF_WM:
                   case OPENLOOK_WM:
                   default:
    @@ -1380,6 +1383,7 @@ Insets guessInsets(XDecoratedPeer window) {
             }
             return res;
         }
    +
         /*
          * Some buggy WMs ignore window gravity when processing
          * ConfigureRequest and position window as if the gravity is Static.
    diff --git a/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java b/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java
    index 81e6ae8375f..b1ba768b8d0 100644
    --- a/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java
    +++ b/src/java.desktop/unix/classes/sun/awt/X11GraphicsEnvironment.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -64,7 +64,7 @@ public Object run() {
                     System.loadLibrary("awt");
     
                     /*
    -                 * Note: The MToolkit object depends on the static initializer
    +                 * Note: The XToolkit object depends on the static initializer
                      * of X11GraphicsEnvironment to initialize the connection to
                      * the X11 server.
                      */
    diff --git a/src/java.desktop/unix/classes/sun/java2d/opengl/GLXGraphicsConfig.java b/src/java.desktop/unix/classes/sun/java2d/opengl/GLXGraphicsConfig.java
    index 6af8e91dff0..440671c455b 100644
    --- a/src/java.desktop/unix/classes/sun/java2d/opengl/GLXGraphicsConfig.java
    +++ b/src/java.desktop/unix/classes/sun/java2d/opengl/GLXGraphicsConfig.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2022, 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
    @@ -217,7 +217,7 @@ public String toString() {
         }
     
         /**
    -     * The following methods are invoked from MToolkit or XToolkit.java and
    +     * The following methods are invoked from XToolkit.java and
          * X11ComponentPeer.java rather than having the X11-dependent
          * implementations hardcoded in those classes.  This way the appropriate
          * actions are taken based on the peer's GraphicsConfig, whether it is
    diff --git a/src/java.desktop/unix/native/common/awt/awt.h b/src/java.desktop/unix/native/common/awt/awt.h
    index dbe236eee47..817707789c9 100644
    --- a/src/java.desktop/unix/native/common/awt/awt.h
    +++ b/src/java.desktop/unix/native/common/awt/awt.h
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1995, 2022, 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
    @@ -41,7 +41,7 @@ typedef char Boolean;
     #endif /* !HEADLESS && !MACOSX */
     
     
    -/* The JVM instance: defined in awt_MToolkit.c */
    +/* The JVM instance: defined in awt_LoadLibrary.c */
     extern JavaVM *jvm;
     
     extern jclass tkClass;
    diff --git a/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java b/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java
    index f4f6747c5d0..7bf4623b2de 100644
    --- a/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java
    +++ b/src/java.desktop/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2003, 2023, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2003, 2024, 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
    @@ -515,7 +515,7 @@ static int compareShellFolders(Win32ShellFolder2 sf1, Win32ShellFolder2 sf2) {
             boolean special1 = sf1.isSpecial();
             boolean special2 = sf2.isSpecial();
     
    -        if (special1 || special2) {
    +        if (special1 && special2) {
                 if (topFolderList == null) {
                     ArrayList tmpTopFolderList = new ArrayList<>();
                     tmpTopFolderList.add(Win32ShellFolderManager2.getPersonal());
    diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/Obj.java b/src/java.naming/share/classes/com/sun/jndi/ldap/Obj.java
    index 5c4b9ab0f6c..dc69b355850 100644
    --- a/src/java.naming/share/classes/com/sun/jndi/ldap/Obj.java
    +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/Obj.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1999, 2022, 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
    @@ -239,6 +239,10 @@ static Object decodeObject(Attributes attrs)
                     ClassLoader cl = helper.getURLClassLoader(codebases);
                     return deserializeObject((byte[])attr.get(), cl);
                 } else if ((attr = attrs.get(JAVA_ATTRIBUTES[REMOTE_LOC])) != null) {
    +                 // javaRemoteLocation attribute (RMI stub will be created)
    +                 if (!VersionHelper.isSerialDataAllowed()) {
    +                     throw new NamingException("Object deserialization is not allowed");
    +                 }
                     // For backward compatibility only
                     return decodeRmiObject(
                         (String)attrs.get(JAVA_ATTRIBUTES[CLASSNAME]).get(),
    diff --git a/src/java.naming/share/classes/com/sun/jndi/ldap/VersionHelper.java b/src/java.naming/share/classes/com/sun/jndi/ldap/VersionHelper.java
    index 93f09e569d7..acc723247b7 100644
    --- a/src/java.naming/share/classes/com/sun/jndi/ldap/VersionHelper.java
    +++ b/src/java.naming/share/classes/com/sun/jndi/ldap/VersionHelper.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1999, 2020, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1999, 2022, 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
    @@ -44,8 +44,8 @@ public final class VersionHelper {
         private static final boolean trustURLCodebase;
     
         /**
    -     * Determines whether objects may be deserialized from the content of
    -     * 'javaSerializedData' attribute.
    +     * Determines whether objects may be deserialized or reconstructed from a content of
    +     * 'javaSerializedData', 'javaRemoteLocation' or 'javaReferenceAddress' LDAP attributes.
          */
         private static final boolean trustSerialData;
     
    @@ -56,10 +56,10 @@ public final class VersionHelper {
                     "com.sun.jndi.ldap.object.trustURLCodebase", "false");
             trustURLCodebase = "true".equalsIgnoreCase(trust);
     
    -        // System property to control whether classes is allowed to be loaded from
    -        // 'javaSerializedData' attribute
    +        // System property to control whether classes are allowed to be loaded from
    +        // 'javaSerializedData', 'javaRemoteLocation' or 'javaReferenceAddress' attributes.
             String trustSerialDataSp = getPrivilegedProperty(
    -                "com.sun.jndi.ldap.object.trustSerialData", "true");
    +                "com.sun.jndi.ldap.object.trustSerialData", "false");
             trustSerialData = "true".equalsIgnoreCase(trustSerialDataSp);
         }
     
    @@ -80,8 +80,9 @@ static VersionHelper getVersionHelper() {
         }
     
         /**
    -     * Returns true if deserialization of objects from 'javaSerializedData'
    -     * and 'javaReferenceAddress' LDAP attributes is allowed.
    +     * Returns true if deserialization or reconstruction of objects from
    +     * 'javaSerializedData', 'javaRemoteLocation' and 'javaReferenceAddress'
    +     * LDAP attributes is allowed.
          *
          * @return true if deserialization is allowed; false - otherwise
          */
    diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java
    index 575ba463c5d..fa811fe20b9 100644
    --- a/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java
    +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Exchange.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2015, 2024, 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
    @@ -28,6 +28,7 @@
     import java.io.IOException;
     import java.lang.System.Logger.Level;
     import java.net.InetSocketAddress;
    +import java.net.ProtocolException;
     import java.net.ProxySelector;
     import java.net.URI;
     import java.net.URISyntaxException;
    @@ -39,6 +40,7 @@
     import java.util.Optional;
     import java.util.concurrent.CompletableFuture;
     import java.util.concurrent.Executor;
    +import java.util.concurrent.atomic.AtomicInteger;
     import java.util.function.Function;
     import java.net.http.HttpClient;
     import java.net.http.HttpHeaders;
    @@ -67,6 +69,8 @@
      */
     final class Exchange {
     
    +    static final int MAX_NON_FINAL_RESPONSES =
    +            Utils.getIntegerNetProperty("jdk.httpclient.maxNonFinalResponses", 8);
         final Logger debug = Utils.getDebugLogger(this::dbgString, Utils.DEBUG);
     
         final HttpRequestImpl request;
    @@ -89,6 +93,8 @@ final class Exchange {
         // exchange so that it can be aborted/timed out mid setup.
         final ConnectionAborter connectionAborter = new ConnectionAborter();
     
    +    final AtomicInteger nonFinalResponses = new AtomicInteger();
    +
         Exchange(HttpRequestImpl request, MultiExchange multi) {
             this.request = request;
             this.upgrading = false;
    @@ -280,7 +286,7 @@ private void checkCancelled() {
     
         public void h2Upgrade() {
             upgrading = true;
    -        request.setH2Upgrade(client.client2());
    +        request.setH2Upgrade(this);
         }
     
         synchronized IOException getCancelCause() {
    @@ -378,6 +384,7 @@ private CompletableFuture expectContinue(ExchangeImpl ex) {
                 Log.logResponse(r1::toString);
                 int rcode = r1.statusCode();
                 if (rcode == 100) {
    +                nonFinalResponses.incrementAndGet();
                     Log.logTrace("Received 100-Continue: sending body");
                     if (debug.on()) debug.log("Received 100-Continue for %s", r1);
                     CompletableFuture cf =
    @@ -410,10 +417,70 @@ private CompletableFuture sendRequestBody(ExchangeImpl ex) {
             CompletableFuture cf = ex.sendBodyAsync()
                     .thenCompose(exIm -> exIm.getResponseAsync(parentExecutor));
             cf = wrapForUpgrade(cf);
    +        // after 101 is handled we check for other 1xx responses
    +        cf = cf.thenCompose(this::ignore1xxResponse);
             cf = wrapForLog(cf);
             return cf;
         }
     
    +    /**
    +     * Checks whether the passed Response has a status code between 102 and 199 (both inclusive).
    +     * If so, then that {@code Response} is considered intermediate informational response and is
    +     * ignored by the client. This method then creates a new {@link CompletableFuture} which
    +     * completes when a subsequent response is sent by the server. Such newly constructed
    +     * {@link CompletableFuture} will not complete till a "final" response (one which doesn't have
    +     * a response code between 102 and 199 inclusive) is sent by the server. The returned
    +     * {@link CompletableFuture} is thus capable of handling multiple subsequent intermediate
    +     * informational responses from the server.
    +     * 

    + * If the passed Response doesn't have a status code between 102 and 199 (both inclusive) then + * this method immediately returns back a completed {@link CompletableFuture} with the passed + * {@code Response}. + *

    + * + * @param rsp The response + * @return A {@code CompletableFuture} with the final response from the server + */ + private CompletableFuture ignore1xxResponse(final Response rsp) { + final int statusCode = rsp.statusCode(); + // we ignore any response code which is 1xx. + // For 100 (with the request configured to expect-continue) and 101, we handle it + // specifically as defined in the RFC-9110, outside of this method. + // As noted in RFC-9110, section 15.2.1, if response code is 100 and if the request wasn't + // configured with expectContinue, then we ignore the 100 response and wait for the final + // response (just like any other 1xx response). + // Any other response code between 102 and 199 (both inclusive) aren't specified in the + // "HTTP semantics" RFC-9110. The spec states that these 1xx response codes are informational + // and interim and the client can choose to ignore them and continue to wait for the + // final response (headers) + if ((statusCode >= 102 && statusCode <= 199) + || (statusCode == 100 && !request.expectContinue)) { + Log.logTrace("Ignoring (1xx informational) response code {0}", rsp.statusCode()); + if (debug.on()) { + debug.log("Ignoring (1xx informational) response code " + + rsp.statusCode()); + } + assert exchImpl != null : "Illegal state - current exchange isn't set"; + int count = nonFinalResponses.incrementAndGet(); + if (MAX_NON_FINAL_RESPONSES > 0 && (count < 0 || count > MAX_NON_FINAL_RESPONSES)) { + return MinimalFuture.failedFuture( + new ProtocolException(String.format( + "Too many interim responses received: %s > %s", + count, MAX_NON_FINAL_RESPONSES))); + } else { + // ignore this Response and wait again for the subsequent response headers + final CompletableFuture cf = exchImpl.getResponseAsync(parentExecutor); + // we recompose the CF again into the ignore1xxResponse check/function because + // the 1xx response is allowed to be sent multiple times for a request, before + // a final response arrives + return cf.thenCompose(this::ignore1xxResponse); + } + } else { + // return the already completed future + return MinimalFuture.completedFuture(rsp); + } + } + CompletableFuture responseAsyncImpl0(HttpConnection connection) { Function, CompletableFuture> after407Check; bodyIgnored = null; @@ -444,7 +511,30 @@ private CompletableFuture wrapForUpgrade(CompletableFuture c if (upgrading) { return cf.thenCompose(r -> checkForUpgradeAsync(r, exchImpl)); } - return cf; + // websocket requests use "Connection: Upgrade" and "Upgrade: websocket" headers. + // however, the "upgrading" flag we maintain in this class only tracks a h2 upgrade + // that we internally triggered. So it will be false in the case of websocket upgrade, hence + // this additional check. If it's a websocket request we allow 101 responses and we don't + // require any additional checks when a response arrives. + if (request.isWebSocket()) { + return cf; + } + // not expecting an upgrade, but if the server sends a 101 response then we fail the + // request and also let the ExchangeImpl deal with it as a protocol error + return cf.thenCompose(r -> { + if (r.statusCode == 101) { + final ProtocolException protoEx = new ProtocolException("Unexpected 101 " + + "response, when not upgrading"); + assert exchImpl != null : "Illegal state - current exchange isn't set"; + try { + exchImpl.onProtocolError(protoEx); + } catch (Throwable ignore){ + // ignored + } + return MinimalFuture.failedFuture(protoEx); + } + return MinimalFuture.completedFuture(r); + }); } private CompletableFuture wrapForLog(CompletableFuture cf) { @@ -486,7 +576,7 @@ HttpResponse.BodySubscriber ignoreBody(HttpResponse.ResponseInfo hdrs) { this, e::drainLeftOverBytes) .thenCompose((Http2Connection c) -> { boolean cached = c.offerConnection(); - Stream s = c.getStream(1); + Stream s = c.getInitialStream(); if (s == null) { // s can be null if an exception occurred @@ -641,6 +731,14 @@ HttpClient.Version version() { return multi.version(); } + boolean pushEnabled() { + return pushGroup != null; + } + + String h2cSettingsStrings() { + return client.client2().getSettingsString(pushEnabled()); + } + String dbgString() { return dbgTag; } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java index e8b3f0b22ca..b1884c13528 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ExchangeImpl.java @@ -199,6 +199,16 @@ abstract CompletableFuture readBodyAsync(HttpResponse.BodyHandler handler, */ abstract void cancel(IOException cause); + /** + * Invoked whenever there is a (HTTP) protocol error when dealing with the response + * from the server. The implementations of {@code ExchangeImpl} are then expected to + * take necessary action that is expected by the corresponding specifications whenever + * a protocol error happens. For example, in HTTP/1.1, such protocol error would result + * in the connection being closed. + * @param cause The cause of the protocol violation + */ + abstract void onProtocolError(IOException cause); + /** * Called when the exchange is released, so that cleanup actions may be * performed - such as deregistering callbacks. diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java index 78462aa962c..d433c39aedb 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Exchange.java @@ -426,6 +426,15 @@ void cancel(IOException cause) { cancelImpl(cause); } + @Override + void onProtocolError(final IOException cause) { + if (debug.on()) { + debug.log("cancelling exchange due to protocol error: %s", cause.getMessage()); + } + Log.logError("cancelling exchange due to protocol error: {0}\n", cause); + cancelImpl(cause); + } + private void cancelImpl(Throwable cause) { LinkedList> toComplete = null; int count = 0; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http1HeaderParser.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http1HeaderParser.java index ac5a59e1db0..a3e25741e68 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1HeaderParser.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1HeaderParser.java @@ -25,6 +25,7 @@ package jdk.internal.net.http; +import java.io.IOException; import java.net.ProtocolException; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -33,6 +34,7 @@ import java.util.Locale; import java.util.Map; import java.net.http.HttpHeaders; +import jdk.internal.net.http.common.Utils; import static java.lang.String.format; import static java.util.Objects.requireNonNull; import static jdk.internal.net.http.common.Utils.ACCEPT_ALL; @@ -49,6 +51,12 @@ class Http1HeaderParser { private int responseCode; private HttpHeaders headers; private Map> privateMap = new HashMap<>(); + private long size; + + private static final int K = 1024; + private static final int MAX_HTTP_HEADER_SIZE = Utils.getIntegerNetProperty( + "jdk.http.maxHeaderSize", + Integer.MIN_VALUE, Integer.MAX_VALUE, 384 * K, true); enum State { INITIAL, STATUS_LINE, @@ -166,11 +174,16 @@ private boolean canContinueParsing(ByteBuffer buffer) { } } - private void readResumeStatusLine(ByteBuffer input) { + private void readResumeStatusLine(ByteBuffer input) throws ProtocolException { + final long max = MAX_HTTP_HEADER_SIZE - size - 32 - sb.length(); + int count = 0; char c = 0; while (input.hasRemaining() && (c =(char)input.get()) != CR) { if (c == LF) break; sb.append(c); + if (++count > max) { + checkMaxHeaderSize(sb.length()); + } } if (c == CR) { state = State.STATUS_LINE_FOUND_CR; @@ -187,6 +200,7 @@ private void readStatusLineFeed(ByteBuffer input) throws ProtocolException { } statusLine = sb.toString(); + size = size + 32 + statusLine.length(); sb = new StringBuilder(); if (!statusLine.startsWith("HTTP/1.")) { throw protocolException("Invalid status line: \"%s\"", statusLine); @@ -199,7 +213,23 @@ private void readStatusLineFeed(ByteBuffer input) throws ProtocolException { state = State.STATUS_LINE_END; } - private void maybeStartHeaders(ByteBuffer input) { + private void checkMaxHeaderSize(int sz) throws ProtocolException { + long s = size + sz + 32; + if (MAX_HTTP_HEADER_SIZE > 0 && s > MAX_HTTP_HEADER_SIZE) { + throw new ProtocolException(String.format("Header size too big: %s > %s", + s, MAX_HTTP_HEADER_SIZE)); + } + } + static private long newSize(long size, int name, int value) throws ProtocolException { + long newSize = size + name + value + 32; + if (MAX_HTTP_HEADER_SIZE > 0 && newSize > MAX_HTTP_HEADER_SIZE) { + throw new ProtocolException(String.format("Header size too big: %s > %s", + newSize, MAX_HTTP_HEADER_SIZE)); + } + return newSize; + } + + private void maybeStartHeaders(ByteBuffer input) throws ProtocolException { assert state == State.STATUS_LINE_END; assert sb.length() == 0; char c = (char)input.get(); @@ -209,6 +239,7 @@ private void maybeStartHeaders(ByteBuffer input) { state = State.STATUS_LINE_END_LF; } else { sb.append(c); + checkMaxHeaderSize(sb.length()); state = State.HEADER; } } @@ -226,9 +257,11 @@ private void maybeEndHeaders(ByteBuffer input) throws ProtocolException { } } - private void readResumeHeader(ByteBuffer input) { + private void readResumeHeader(ByteBuffer input) throws ProtocolException { assert state == State.HEADER; assert input.hasRemaining(); + final long max = MAX_HTTP_HEADER_SIZE - size - 32 - sb.length(); + int count = 0; while (input.hasRemaining()) { char c = (char)input.get(); if (c == CR) { @@ -242,10 +275,13 @@ private void readResumeHeader(ByteBuffer input) { if (c == HT) c = SP; sb.append(c); + if (++count > max) { + checkMaxHeaderSize(sb.length()); + } } } - private void addHeaderFromString(String headerString) { + private void addHeaderFromString(String headerString) throws ProtocolException { assert sb.length() == 0; int idx = headerString.indexOf(':'); if (idx == -1) @@ -254,12 +290,12 @@ private void addHeaderFromString(String headerString) { if (name.isEmpty()) return; String value = headerString.substring(idx + 1, headerString.length()).trim(); - + size = newSize(size, name.length(), value.length()); privateMap.computeIfAbsent(name.toLowerCase(Locale.US), k -> new ArrayList<>()).add(value); } - private void resumeOrLF(ByteBuffer input) { + private void resumeOrLF(ByteBuffer input) throws ProtocolException { assert state == State.HEADER_FOUND_CR || state == State.HEADER_FOUND_LF; char c = state == State.HEADER_FOUND_LF ? LF : (char)input.get(); if (c == LF) { @@ -269,15 +305,17 @@ private void resumeOrLF(ByteBuffer input) { state = State.HEADER_FOUND_CR_LF; } else if (c == SP || c == HT) { sb.append(SP); // parity with MessageHeaders + checkMaxHeaderSize(sb.length()); state = State.HEADER; } else { sb = new StringBuilder(); sb.append(c); + checkMaxHeaderSize(1); state = State.HEADER; } } - private void resumeOrSecondCR(ByteBuffer input) { + private void resumeOrSecondCR(ByteBuffer input) throws ProtocolException { assert state == State.HEADER_FOUND_CR_LF; char c = (char)input.get(); if (c == CR || c == LF) { @@ -298,6 +336,7 @@ private void resumeOrSecondCR(ByteBuffer input) { } else if (c == SP || c == HT) { assert sb.length() != 0; sb.append(SP); // continuation line + checkMaxHeaderSize(sb.length()); state = State.HEADER; } else { if (sb.length() > 0) { @@ -308,6 +347,7 @@ private void resumeOrSecondCR(ByteBuffer input) { addHeaderFromString(headerString); } sb.append(c); + checkMaxHeaderSize(sb.length()); state = State.HEADER; } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java index 6bd9bad2da5..0f2db7738fc 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2ClientImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -38,7 +38,6 @@ import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CompletableFuture; -import jdk.internal.net.http.common.Log; import jdk.internal.net.http.common.Logger; import jdk.internal.net.http.common.MinimalFuture; import jdk.internal.net.http.common.Utils; @@ -48,6 +47,7 @@ import static jdk.internal.net.http.frame.SettingsFrame.HEADER_TABLE_SIZE; import static jdk.internal.net.http.frame.SettingsFrame.MAX_CONCURRENT_STREAMS; import static jdk.internal.net.http.frame.SettingsFrame.MAX_FRAME_SIZE; +import static jdk.internal.net.http.frame.SettingsFrame.MAX_HEADER_LIST_SIZE; /** * Http2 specific aspects of HttpClientImpl @@ -93,17 +93,20 @@ class Http2ClientImpl { */ CompletableFuture getConnectionFor(HttpRequestImpl req, Exchange exchange) { - URI uri = req.uri(); - InetSocketAddress proxy = req.proxy(); - String key = Http2Connection.keyFor(uri, proxy); + String key = Http2Connection.keyFor(req); + boolean pushEnabled = exchange.pushEnabled(); synchronized (this) { Http2Connection connection = connections.get(key); if (connection != null) { try { - if (connection.closed || !connection.reserveStream(true)) { + if (connection.closed + || !connection.reserveStream(true, pushEnabled)) { if (debug.on()) - debug.log("removing found closed or closing connection: %s", connection); + debug.log("removing connection from pool since " + + "it couldn't be reserved for use%s: %s", + pushEnabled ? " with server push enabled" : + "", connection); deleteConnection(connection); } else { // fast path if connection already exists @@ -130,7 +133,7 @@ CompletableFuture getConnectionFor(HttpRequestImpl req, synchronized (Http2ClientImpl.this) { if (conn != null) { try { - conn.reserveStream(true); + conn.reserveStream(true, exchange.pushEnabled()); } catch (IOException e) { throw new UncheckedIOException(e); // shouldn't happen } @@ -163,10 +166,21 @@ boolean offerConnection(Http2Connection c) { synchronized(this) { Http2Connection c1 = connections.putIfAbsent(key, c); if (c1 != null) { - c.setFinalStream(); - if (debug.on()) - debug.log("existing entry in connection pool for %s", key); - return false; + if (c.serverPushEnabled() && !c1.serverPushEnabled()) { + c1.setFinalStream(); + connections.remove(key, c1); + connections.put(key, c); + if (debug.on()) { + debug.log("Replacing %s with %s in connection pool", c1, c); + } + if (c1.shouldClose()) c1.close(); + return true; + } else { + c.setFinalStream(); + if (debug.on()) + debug.log("existing entry in connection pool for %s", key); + return false; + } } if (debug.on()) debug.log("put in the connection pool: %s", c); @@ -206,8 +220,8 @@ HttpClientImpl client() { } /** Returns the client settings as a base64 (url) encoded string */ - String getSettingsString() { - SettingsFrame sf = getClientSettings(); + String getSettingsString(boolean defaultServerPush) { + SettingsFrame sf = getClientSettings(defaultServerPush); byte[] settings = sf.toByteArray(); // without the header Base64.Encoder encoder = Base64.getUrlEncoder() .withoutPadding(); @@ -217,14 +231,7 @@ String getSettingsString() { private static final int K = 1024; private static int getParameter(String property, int min, int max, int defaultValue) { - int value = Utils.getIntegerNetProperty(property, defaultValue); - // use default value if misconfigured - if (value < min || value > max) { - Log.logError("Property value for {0}={1} not in [{2}..{3}]: " + - "using default={4}", property, value, min, max, defaultValue); - value = defaultValue; - } - return value; + return Utils.getIntegerNetProperty(property, min, max, defaultValue, true); } // used for the connection window, to have a connection window size @@ -245,7 +252,18 @@ int getConnectionWindowSize(SettingsFrame clientSettings) { streamWindow, Integer.MAX_VALUE, defaultValue); } - SettingsFrame getClientSettings() { + /** + * This method is used to test whether pushes are globally + * disabled on all connections. + * @return true if pushes are globally disabled on all connections + */ + boolean serverPushDisabled() { + return getParameter( + "jdk.httpclient.enablepush", + 0, 1, 1) == 0; + } + + SettingsFrame getClientSettings(boolean defaultServerPush) { SettingsFrame frame = new SettingsFrame(); // default defined for HTTP/2 is 4 K, we use 16 K. frame.setParameter(HEADER_TABLE_SIZE, getParameter( @@ -254,14 +272,15 @@ SettingsFrame getClientSettings() { // O: does not accept push streams. 1: accepts push streams. frame.setParameter(ENABLE_PUSH, getParameter( "jdk.httpclient.enablepush", - 0, 1, 1)); + 0, 1, defaultServerPush ? 1 : 0)); // HTTP/2 recommends to set the number of concurrent streams - // no lower than 100. We use 100. 0 means no stream would be - // accepted. That would render the client to be non functional, - // so we won't let 0 be configured for our Http2ClientImpl. + // no lower than 100. We use 100, unless push promises are + // disabled. + int initialServerStreams = frame.getParameter(ENABLE_PUSH) == 0 + ? 0 : 100; frame.setParameter(MAX_CONCURRENT_STREAMS, getParameter( "jdk.httpclient.maxstreams", - 1, Integer.MAX_VALUE, 100)); + 0, Integer.MAX_VALUE, initialServerStreams)); // Maximum size is 2^31-1. Don't allow window size to be less // than the minimum frame size as this is likely to be a // configuration error. HTTP/2 specify a default of 64 * K -1, @@ -274,6 +293,14 @@ SettingsFrame getClientSettings() { frame.setParameter(MAX_FRAME_SIZE, getParameter( "jdk.httpclient.maxframesize", 16 * K, 16 * K * K -1, 16 * K)); + // Maximum field section size we're prepared to accept + // This is the uncompressed name + value size + 32 per field line + int maxHeaderSize = getParameter( + "jdk.http.maxHeaderSize", + Integer.MIN_VALUE, Integer.MAX_VALUE, 384 * K); + // If the property is <= 0 the value is unlimited + if (maxHeaderSize <= 0) maxHeaderSize = -1; + frame.setParameter(MAX_HEADER_LIST_SIZE, maxHeaderSize); return frame; } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java index 5c0f8c2409c..2953b297561 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -29,6 +29,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.net.InetSocketAddress; +import java.net.ProtocolException; import java.net.URI; import java.nio.ByteBuffer; import java.nio.charset.StandardCharsets; @@ -44,6 +45,8 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.Flow; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.util.function.Supplier; import javax.net.ssl.SSLEngine; @@ -53,12 +56,14 @@ import jdk.internal.net.http.HttpConnection.HttpPublisher; import jdk.internal.net.http.common.FlowTube; import jdk.internal.net.http.common.FlowTube.TubeSubscriber; +import jdk.internal.net.http.common.HeaderDecoder; import jdk.internal.net.http.common.HttpHeadersBuilder; import jdk.internal.net.http.common.Log; import jdk.internal.net.http.common.Logger; import jdk.internal.net.http.common.MinimalFuture; import jdk.internal.net.http.common.SequentialScheduler; import jdk.internal.net.http.common.Utils; +import jdk.internal.net.http.common.ValidatingHeadersConsumer; import jdk.internal.net.http.frame.ContinuationFrame; import jdk.internal.net.http.frame.DataFrame; import jdk.internal.net.http.frame.ErrorFrame; @@ -243,6 +248,55 @@ void markPrefaceSent() { } } + private final class PushContinuationState { + final PushPromiseDecoder pushContDecoder; + final PushPromiseFrame pushContFrame; + + PushContinuationState(PushPromiseDecoder pushContDecoder, PushPromiseFrame pushContFrame) { + this.pushContDecoder = pushContDecoder; + this.pushContFrame = pushContFrame; + } + } + + private final class PushPromiseDecoder extends HeaderDecoder implements DecodingCallback { + + final int parentStreamId; + final int pushPromiseStreamId; + final Stream parent; + final AtomicReference errorRef = new AtomicReference<>(); + + PushPromiseDecoder(int parentStreamId, int pushPromiseStreamId, Stream parent) { + this.parentStreamId = parentStreamId; + this.pushPromiseStreamId = pushPromiseStreamId; + this.parent = parent; + } + + @Override + protected void addHeader(String name, String value) { + if (errorRef.get() == null) { + super.addHeader(name, value); + } + } + + @Override + public void onMaxHeaderListSizeReached(long size, int maxHeaderListSize) throws ProtocolException { + try { + DecodingCallback.super.onMaxHeaderListSizeReached(size, maxHeaderListSize); + } catch (ProtocolException pe) { + if (parent != null) { + if (errorRef.compareAndSet(null, pe)) { + // cancel the parent stream + resetStream(pushPromiseStreamId, ResetFrame.REFUSED_STREAM); + parent.onProtocolError(pe); + } + } else { + // interrupt decoding and closes the connection + throw pe; + } + } + } + } + volatile boolean closed; //------------------------------------- @@ -263,6 +317,7 @@ void markPrefaceSent() { private final Decoder hpackIn; final SettingsFrame clientSettings; private volatile SettingsFrame serverSettings; + private volatile PushContinuationState pushContinuationState; private final String key; // for HttpClientImpl.connections map private final FramesDecoder framesDecoder; private final FramesEncoder framesEncoder = new FramesEncoder(); @@ -275,11 +330,24 @@ void markPrefaceSent() { private final FramesController framesController = new FramesController(); private final Http2TubeSubscriber subscriber; final ConnectionWindowUpdateSender windowUpdater; - private volatile Throwable cause; + private final AtomicReference cause = new AtomicReference<>(); private volatile Supplier initial; + private volatile Stream initialStream; + + private ValidatingHeadersConsumer orphanedConsumer; + private final AtomicInteger orphanedHeaders = new AtomicInteger(); static final int DEFAULT_FRAME_SIZE = 16 * 1024; + static final int MAX_LITERAL_WITH_INDEXING = + Utils.getIntegerNetProperty("jdk.httpclient.maxLiteralWithIndexing",512); + // The maximum number of HEADER frames, CONTINUATION frames, or PUSH_PROMISE frames + // referring to an already closed or non-existent stream that a client will accept to + // process. Receiving frames referring to non-existent or closed streams doesn't necessarily + // constitute an HTTP/2 protocol error, but receiving too many may indicate a problem + // with the connection. If this limit is reached, a {@link java.net.ProtocolException + // ProtocolException} will be raised and the connection will be closed. + static final int MAX_ORPHANED_HEADERS = 1024; // TODO: need list of control frames from other threads // that need to be sent @@ -287,19 +355,21 @@ void markPrefaceSent() { private Http2Connection(HttpConnection connection, Http2ClientImpl client2, int nextstreamid, - String key) { + String key, + boolean defaultServerPush) { this.connection = connection; this.client2 = client2; this.subscriber = new Http2TubeSubscriber(client2.client()); this.nextstreamid = nextstreamid; this.key = key; - this.clientSettings = this.client2.getClientSettings(); + this.clientSettings = this.client2.getClientSettings(defaultServerPush); this.framesDecoder = new FramesDecoder(this::processFrame, clientSettings.getParameter(SettingsFrame.MAX_FRAME_SIZE)); // serverSettings will be updated by server this.serverSettings = SettingsFrame.defaultRFCSettings(); this.hpackOut = new Encoder(serverSettings.getParameter(HEADER_TABLE_SIZE)); - this.hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE)); + this.hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE), + clientSettings.getParameter(MAX_HEADER_LIST_SIZE), MAX_LITERAL_WITH_INDEXING); if (debugHpack.on()) { debugHpack.log("For the record:" + super.toString()); debugHpack.log("Decoder created: %s", hpackIn); @@ -318,18 +388,25 @@ private Http2Connection(HttpConnection connection, private Http2Connection(HttpConnection connection, Http2ClientImpl client2, Exchange exchange, - Supplier initial) + Supplier initial, + boolean defaultServerPush) throws IOException, InterruptedException { this(connection, client2, 3, // stream 1 is registered during the upgrade - keyFor(connection)); - reserveStream(true); + keyFor(connection), + defaultServerPush); + reserveStream(true, clientSettings.getFlag(ENABLE_PUSH)); Log.logTrace("Connection send window size {0} ", windowController.connectionWindowSize()); Stream initialStream = createStream(exchange); - initialStream.registerStream(1); + boolean opened = initialStream.registerStream(1, true); + this.initialStream = initialStream; + if (debug.on() && !opened) { + debug.log("Initial stream was cancelled - but connection is maintained: " + + "reset frame will need to be sent later"); + } windowController.registerStream(1, getInitialSendWindowSize()); initialStream.requestSent(); // Upgrading: @@ -338,6 +415,11 @@ private Http2Connection(HttpConnection connection, this.initial = initial; connectFlows(connection); sendConnectionPreface(); + if (!opened) { + debug.log("ensure reset frame is sent to cancel initial stream"); + initialStream.sendResetStreamFrame(ResetFrame.CANCEL); + } + } // Used when upgrading an HTTP/1.1 connection to HTTP/2 after receiving @@ -348,7 +430,8 @@ static CompletableFuture createAsync(HttpConnection connection, Exchange exchange, Supplier initial) { - return MinimalFuture.supply(() -> new Http2Connection(connection, client2, exchange, initial)); + return MinimalFuture.supply(() -> new Http2Connection(connection, client2, exchange, initial, + exchange.pushEnabled())); } // Requires TLS handshake. So, is really async @@ -372,7 +455,8 @@ static CompletableFuture createAsync(HttpRequestImpl request, .thenCompose(notused-> { CompletableFuture cf = new MinimalFuture<>(); try { - Http2Connection hc = new Http2Connection(request, h2client, connection); + Http2Connection hc = new Http2Connection(request, h2client, + connection, exchange.pushEnabled()); cf.complete(hc); } catch (IOException e) { cf.completeExceptionally(e); @@ -387,13 +471,15 @@ static CompletableFuture createAsync(HttpRequestImpl request, */ private Http2Connection(HttpRequestImpl request, Http2ClientImpl h2client, - HttpConnection connection) + HttpConnection connection, + boolean defaultServerPush) throws IOException { this(connection, h2client, 1, - keyFor(request.uri(), request.proxy())); + keyFor(request), + defaultServerPush); Log.logTrace("Connection send window size {0} ", windowController.connectionWindowSize()); @@ -416,15 +502,21 @@ final HttpClientImpl client() { // if false returned then a new Http2Connection is required // if true, the the stream may be assigned to this connection // for server push, if false returned, then the stream should be cancelled - synchronized boolean reserveStream(boolean clientInitiated) throws IOException { + synchronized boolean reserveStream(boolean clientInitiated, boolean pushEnabled) throws IOException { if (finalStream) { return false; } - if (clientInitiated && (lastReservedClientStreamid + 2) >= MAX_CLIENT_STREAM_ID) { + // If requesting to reserve a stream for an exchange for which push is enabled, + // we will reserve the stream in this connection only if this connection is also + // push enabled, unless pushes are globally disabled. + boolean pushCompatible = !clientInitiated || !pushEnabled + || this.serverPushEnabled() + || client2.serverPushDisabled(); + if (clientInitiated && (lastReservedClientStreamid >= MAX_CLIENT_STREAM_ID -2 || !pushCompatible)) { setFinalStream(); client2.deleteConnection(this); return false; - } else if (!clientInitiated && (lastReservedServerStreamid + 2) >= MAX_SERVER_STREAM_ID) { + } else if (!clientInitiated && (lastReservedServerStreamid >= MAX_SERVER_STREAM_ID - 2)) { setFinalStream(); client2.deleteConnection(this); return false; @@ -449,6 +541,10 @@ synchronized boolean reserveStream(boolean clientInitiated) throws IOException { return true; } + synchronized boolean shouldClose() { + return finalStream() && streams.isEmpty(); + } + /** * Throws an IOException if h2 was not negotiated */ @@ -520,15 +616,13 @@ static String keyFor(HttpConnection connection) { return keyString(isSecure, proxyAddr, addr.getHostString(), addr.getPort()); } - static String keyFor(URI uri, InetSocketAddress proxy) { - boolean isSecure = uri.getScheme().equalsIgnoreCase("https"); - - String host = uri.getHost(); - int port = uri.getPort(); - return keyString(isSecure, proxy, host, port); + static String keyFor(final HttpRequestImpl request) { + final InetSocketAddress targetAddr = request.getAddress(); + final InetSocketAddress proxy = request.proxy(); + final boolean secure = request.secure(); + return keyString(secure, proxy, targetAddr.getHostString(), targetAddr.getPort()); } - // Compute the key for an HttpConnection in the Http2ClientImpl pool: // The key string follows one of the three forms below: // {C,S}:H:host:port @@ -573,6 +667,10 @@ String key() { return this.key; } + public boolean serverPushEnabled() { + return clientSettings.getParameter(SettingsFrame.ENABLE_PUSH) == 1; + } + boolean offerConnection() { return client2.offerConnection(this); } @@ -671,7 +769,7 @@ final void asyncReceive(ByteBuffer buffer) { } Throwable getRecordedCause() { - return cause; + return cause.get(); } void shutdown(Throwable t) { @@ -681,6 +779,7 @@ void shutdown(Throwable t) { if (closed == true) return; closed = true; } + cause.compareAndSet(null, t); if (Log.errors()) { if (!(t instanceof EOFException) || isActive()) { Log.logError(t); @@ -688,9 +787,8 @@ void shutdown(Throwable t) { Log.logError("Shutting down connection: {0}", t.getMessage()); } } - Throwable initialCause = this.cause; - if (initialCause == null) this.cause = t; client2.deleteConnection(this); + subscriber.stop(cause.get()); List> c = new LinkedList<>(streams.values()); for (Stream s : c) { try { @@ -745,17 +843,39 @@ void processFrame(Http2Frame frame) throws IOException { return; } + if (frame instanceof PushPromiseFrame && !serverPushEnabled()) { + String protocolError = "received a PUSH_PROMISE when SETTINGS_ENABLE_PUSH is 0"; + protocolError(ResetFrame.PROTOCOL_ERROR, protocolError); + return; + } + Stream stream = getStream(streamid); - if (stream == null) { + var nextstreamid = this.nextstreamid; + if (stream == null && (streamid & 0x01) == 0x01 && streamid >= nextstreamid) { + String protocolError = String.format( + "received a frame for a non existing streamid(%s) >= nextstreamid(%s)", + streamid, nextstreamid); + protocolError(ResetFrame.PROTOCOL_ERROR, protocolError); + return; + } + if (stream == null && pushContinuationState == null) { // Should never receive a frame with unknown stream id if (frame instanceof HeaderFrame) { + String protocolError = checkMaxOrphanedHeadersExceeded((HeaderFrame)frame); + if (protocolError != null) { + protocolError(ResetFrame.PROTOCOL_ERROR, protocolError); + return; + } // always decode the headers as they may affect // connection-level HPACK decoding state - DecodingCallback decoder = new ValidatingHeadersConsumer(); + if (orphanedConsumer == null || frame.getClass() != ContinuationFrame.class) { + orphanedConsumer = new ValidatingHeadersConsumer(); + } + DecodingCallback decoder = orphanedConsumer::onDecoded; try { - decodeHeaders((HeaderFrame) frame, decoder); - } catch (UncheckedIOException e) { + decodeHeaders((HeaderFrame)frame, decoder); + } catch (IOException | UncheckedIOException e) { protocolError(ResetFrame.PROTOCOL_ERROR, e.getMessage()); return; } @@ -780,29 +900,75 @@ void processFrame(Http2Frame frame) throws IOException { } return; } - if (frame instanceof PushPromiseFrame) { - PushPromiseFrame pp = (PushPromiseFrame)frame; - try { - handlePushPromise(stream, pp); - } catch (UncheckedIOException e) { - protocolError(ResetFrame.PROTOCOL_ERROR, e.getMessage()); - return; - } - } else if (frame instanceof HeaderFrame) { - // decode headers (or continuation) - try { - decodeHeaders((HeaderFrame) frame, stream.rspHeadersConsumer()); - } catch (UncheckedIOException e) { - protocolError(ResetFrame.PROTOCOL_ERROR, e.getMessage()); + + // While push frame is not null, the only acceptable frame on this + // stream is a Continuation frame + PushContinuationState pcs = pushContinuationState; + if (pcs != null) { + if (frame instanceof ContinuationFrame) { + ContinuationFrame cf = (ContinuationFrame)frame; + if (stream == null) { + String protocolError = checkMaxOrphanedHeadersExceeded(cf); + if (protocolError != null) { + protocolError(ResetFrame.PROTOCOL_ERROR, protocolError); + return; + } + } + try { + if (streamid == pcs.pushContFrame.streamid()) + handlePushContinuation(pcs, stream, cf); + else { + String protocolError = "Received a CONTINUATION with " + + "unexpected stream id: " + streamid + " != " + + pcs.pushContFrame.streamid(); + protocolError(ErrorFrame.PROTOCOL_ERROR, protocolError); + } + } catch (IOException | UncheckedIOException e) { + debug.log("Error handling Push Promise with Continuation: " + e.getMessage(), e); + protocolError(ErrorFrame.PROTOCOL_ERROR, e.getMessage()); + return; + } + } else { + pushContinuationState = null; + String protocolError = "Expected a CONTINUATION frame but received " + frame; + protocolError(ErrorFrame.PROTOCOL_ERROR, protocolError); return; } - stream.incoming(frame); } else { - stream.incoming(frame); + if (frame instanceof PushPromiseFrame) { + try { + handlePushPromise(stream, (PushPromiseFrame)frame); + } catch (IOException | UncheckedIOException e) { + protocolError(ErrorFrame.PROTOCOL_ERROR, e.getMessage()); + return; + } + } else if (frame instanceof HeaderFrame) { + // decode headers + try { + decodeHeaders((HeaderFrame)frame, stream.rspHeadersConsumer()); + } catch (IOException | UncheckedIOException e) { + debug.log("Error decoding headers: " + e.getMessage(), e); + protocolError(ErrorFrame.PROTOCOL_ERROR, e.getMessage()); + return; + } + stream.incoming(frame); + } else { + stream.incoming(frame); + } } } } + private String checkMaxOrphanedHeadersExceeded(HeaderFrame hf) { + if (MAX_ORPHANED_HEADERS > 0 ) { + int orphaned = orphanedHeaders.incrementAndGet(); + if (orphaned < 0 || orphaned > MAX_ORPHANED_HEADERS) { + return "Too many orphaned header frames received on connection"; + } + } + return null; + } + final void dropDataFrame(DataFrame df) { if (closed) return; if (debug.on()) { @@ -827,29 +993,76 @@ final void ensureWindowUpdated(DataFrame df) { private void handlePushPromise(Stream parent, PushPromiseFrame pp) throws IOException { + int promisedStreamid = pp.getPromisedStream(); + if ((promisedStreamid & 0x01) != 0x00) { + throw new ProtocolException("Received PUSH_PROMISE for stream " + promisedStreamid); + } + int streamId = pp.streamid(); + if ((streamId & 0x01) != 0x01) { + throw new ProtocolException("Received PUSH_PROMISE on stream " + streamId); + } // always decode the headers as they may affect connection-level HPACK // decoding state - HeaderDecoder decoder = new HeaderDecoder(); + assert pushContinuationState == null; + PushPromiseDecoder decoder = new PushPromiseDecoder(streamId, promisedStreamid, parent); decodeHeaders(pp, decoder); + if (pp.endHeaders()) { + if (decoder.errorRef.get() == null) { + completePushPromise(promisedStreamid, parent, decoder.headers()); + } + } else { + pushContinuationState = new PushContinuationState(decoder, pp); + } + } + + private void handlePushContinuation(PushContinuationState pcs, Stream parent, ContinuationFrame cf) + throws IOException { + assert pcs.pushContFrame.streamid() == cf.streamid() : String.format( + "Received CONTINUATION on a different stream %s != %s", + cf.streamid(), pcs.pushContFrame.streamid()); + decodeHeaders(cf, pcs.pushContDecoder); + // if all continuations are sent, set pushWithContinuation to null + if (cf.endHeaders()) { + if (pcs.pushContDecoder.errorRef.get() == null) { + completePushPromise(pcs.pushContFrame.getPromisedStream(), parent, + pcs.pushContDecoder.headers()); + } + pushContinuationState = null; + } + } + private void completePushPromise(int promisedStreamid, Stream parent, HttpHeaders headers) + throws IOException { + if (parent == null) { + resetStream(promisedStreamid, ResetFrame.REFUSED_STREAM); + return; + } HttpRequestImpl parentReq = parent.request; - int promisedStreamid = pp.getPromisedStream(); + if (promisedStreamid < nextPushStream) { + // From RFC 9113 section 5.1.1: + // The identifier of a newly established stream MUST be numerically + // greater than all streams that the initiating endpoint has + // opened or reserved. + protocolError(ResetFrame.PROTOCOL_ERROR, String.format( + "Unexpected stream identifier: %s < %s", promisedStreamid, nextPushStream)); + return; + } if (promisedStreamid != nextPushStream) { + // we don't support skipping stream ids; resetStream(promisedStreamid, ResetFrame.PROTOCOL_ERROR); return; - } else if (!reserveStream(false)) { + } else if (!reserveStream(false, true)) { resetStream(promisedStreamid, ResetFrame.REFUSED_STREAM); return; } else { nextPushStream += 2; } - HttpHeaders headers = decoder.headers(); HttpRequestImpl pushReq = HttpRequestImpl.createPushRequest(parentReq, headers); Exchange pushExch = new Exchange<>(pushReq, parent.exchange.multi); Stream.PushedStream pushStream = createPushStream(parent, pushExch); pushExch.exchImpl = pushStream; - pushStream.registerStream(promisedStreamid); + pushStream.registerStream(promisedStreamid, true); parent.incoming_pushPromise(pushReq, pushStream); } @@ -874,7 +1087,7 @@ private void handleConnectionFrame(Http2Frame frame) } } - void resetStream(int streamid, int code) throws IOException { + void resetStream(int streamid, int code) { try { if (connection.channel().isOpen()) { // no need to try & send a reset frame if the @@ -882,6 +1095,7 @@ void resetStream(int streamid, int code) throws IOException { Log.logError( "Resetting stream {0,number,integer} with error code {1,number,integer}", streamid, code); + markStream(streamid, code); ResetFrame frame = new ResetFrame(streamid, code); sendFrame(frame); } else if (debug.on()) { @@ -894,6 +1108,11 @@ void resetStream(int streamid, int code) throws IOException { } } + private void markStream(int streamid, int code) { + Stream s = streams.get(streamid); + if (s != null) s.markStream(code); + } + // reduce count of streams by 1 if stream still exists synchronized void decrementStreamsCount(int streamid) { Stream s = streams.get(streamid); @@ -961,9 +1180,15 @@ private void protocolError(int errorCode) private void protocolError(int errorCode, String msg) throws IOException { + String protocolError = "protocol error" + (msg == null?"":(": " + msg)); + ProtocolException protocolException = + new ProtocolException(protocolError); + framesDecoder.close(protocolError); + subscriber.stop(protocolException); + if (debug.on()) debug.log("Sending GOAWAY due to " + protocolException); GoAwayFrame frame = new GoAwayFrame(0, errorCode); sendFrame(frame); - shutdown(new IOException("protocol error" + (msg == null?"":(": " + msg)))); + shutdown(protocolException); } private void handleSettings(SettingsFrame frame) @@ -1070,6 +1295,21 @@ private void sendConnectionPreface() throws IOException { subscriber.onNext(List.of(EMPTY_TRIGGER)); } + /** + * Called to get the initial stream after a connection upgrade. + * If the stream was cancelled, it might no longer be in the + * stream map. Therefore - we use the initialStream field + * instead, and reset it to null after returning it. + * @param the response type + * @return the initial stream created during the upgrade. + */ + @SuppressWarnings("unchecked") + Stream getInitialStream() { + var s = (Stream) initialStream; + initialStream = null; + return s; + } + /** * Returns an existing Stream with given id, or null if doesn't exist */ @@ -1088,7 +1328,7 @@ final Stream createStream(Exchange exchange) { Stream.PushedStream createPushStream(Stream parent, Exchange pushEx) { PushGroup pg = parent.exchange.getPushGroup(); - return new Stream.PushedStream<>(pg, this, pushEx); + return new Stream.PushedStream<>(parent, pg, this, pushEx); } void putStream(Stream stream, int streamid) { @@ -1150,16 +1390,18 @@ private ByteBuffer getHeaderBuffer(int size) { private List encodeHeadersImpl(int bufferSize, HttpHeaders... headers) { ByteBuffer buffer = getHeaderBuffer(bufferSize); List buffers = new ArrayList<>(); - for(HttpHeaders header : headers) { + for (HttpHeaders header : headers) { for (Map.Entry> e : header.map().entrySet()) { String lKey = e.getKey().toLowerCase(Locale.US); List values = e.getValue(); for (String value : values) { hpackOut.header(lKey, value); while (!hpackOut.encode(buffer)) { - buffer.flip(); - buffers.add(buffer); - buffer = getHeaderBuffer(bufferSize); + if (!buffer.hasRemaining()) { + buffer.flip(); + buffers.add(buffer); + buffer = getHeaderBuffer(bufferSize); + } } } } @@ -1195,12 +1437,19 @@ private Stream registerNewStream(OutgoingHeaders> oh) { Stream stream = oh.getAttachment(); assert stream.streamid == 0; int streamid = nextstreamid; - nextstreamid += 2; - stream.registerStream(streamid); - // set outgoing window here. This allows thread sending - // body to proceed. - windowController.registerStream(streamid, getInitialSendWindowSize()); - return stream; + if (stream.registerStream(streamid, false)) { + // set outgoing window here. This allows thread sending + // body to proceed. + nextstreamid += 2; + windowController.registerStream(streamid, getInitialSendWindowSize()); + return stream; + } else { + stream.cancelImpl(new IOException("Request cancelled")); + if (finalStream() && streams.isEmpty()) { + close(); + } + return null; + } } private final Object sendlock = new Object(); @@ -1214,7 +1463,11 @@ void sendFrame(Http2Frame frame) { OutgoingHeaders> oh = (OutgoingHeaders>) frame; Stream stream = registerNewStream(oh); // provide protection from inserting unordered frames between Headers and Continuation - publisher.enqueue(encodeHeaders(oh, stream)); + if (stream != null) { + // we are creating a new stream: reset orphaned header count + orphanedHeaders.set(0); + publisher.enqueue(encodeHeaders(oh, stream)); + } } else { publisher.enqueue(encodeFrame(frame)); } @@ -1271,7 +1524,7 @@ final class Http2TubeSubscriber implements TubeSubscriber { private volatile Flow.Subscription subscription; private volatile boolean completed; private volatile boolean dropped; - private volatile Throwable error; + private final AtomicReference errorRef = new AtomicReference<>(); private final ConcurrentLinkedQueue queue = new ConcurrentLinkedQueue<>(); private final SequentialScheduler scheduler = @@ -1292,10 +1545,9 @@ final void processQueue() { asyncReceive(buffer); } } catch (Throwable t) { - Throwable x = error; - if (x == null) error = t; + errorRef.compareAndSet(null, t); } finally { - Throwable x = error; + Throwable x = errorRef.get(); if (x != null) { if (debug.on()) debug.log("Stopping scheduler", x); scheduler.stop(); @@ -1330,6 +1582,7 @@ public void onSubscribe(Flow.Subscription subscription) { @Override public void onNext(List item) { + if (completed) return; if (debug.on()) debug.log(() -> "onNext: got " + Utils.remaining(item) + " bytes in " + item.size() + " buffers"); queue.addAll(item); @@ -1338,19 +1591,21 @@ public void onNext(List item) { @Override public void onError(Throwable throwable) { + if (completed) return; if (debug.on()) debug.log(() -> "onError: " + throwable); - error = throwable; + errorRef.compareAndSet(null, throwable); completed = true; runOrSchedule(); } @Override public void onComplete() { + if (completed) return; String msg = isActive() ? "EOF reached while reading" : "Idle connection closed by HTTP/2 peer"; if (debug.on()) debug.log(msg); - error = new EOFException(msg); + errorRef.compareAndSet(null, new EOFException(msg)); completed = true; runOrSchedule(); } @@ -1362,6 +1617,18 @@ public void dropSubscription() { // then we might not need the 'dropped' boolean? dropped = true; } + + void stop(Throwable error) { + if (errorRef.compareAndSet(null, error)) { + completed = true; + scheduler.stop(); + queue.clear(); + if (subscription != null) { + subscription.cancel(); + } + queue.clear(); + } + } } synchronized boolean isActive() { @@ -1378,76 +1645,6 @@ final String dbgString() { + connection.getConnectionFlow() + ")"; } - static class HeaderDecoder extends ValidatingHeadersConsumer { - - HttpHeadersBuilder headersBuilder; - - HeaderDecoder() { - this.headersBuilder = new HttpHeadersBuilder(); - } - - @Override - public void onDecoded(CharSequence name, CharSequence value) { - String n = name.toString(); - String v = value.toString(); - super.onDecoded(n, v); - headersBuilder.addHeader(n, v); - } - - HttpHeaders headers() { - return headersBuilder.build(); - } - } - - /* - * Checks RFC 7540 rules (relaxed) compliance regarding pseudo-headers. - */ - static class ValidatingHeadersConsumer implements DecodingCallback { - - private static final Set PSEUDO_HEADERS = - Set.of(":authority", ":method", ":path", ":scheme", ":status"); - - /** Used to check that if there are pseudo-headers, they go first */ - private boolean pseudoHeadersEnded; - - /** - * Called when END_HEADERS was received. This consumer may be invoked - * again after reset() is called, but for a whole new set of headers. - */ - void reset() { - pseudoHeadersEnded = false; - } - - @Override - public void onDecoded(CharSequence name, CharSequence value) - throws UncheckedIOException - { - String n = name.toString(); - if (n.startsWith(":")) { - if (pseudoHeadersEnded) { - throw newException("Unexpected pseudo-header '%s'", n); - } else if (!PSEUDO_HEADERS.contains(n)) { - throw newException("Unknown pseudo-header '%s'", n); - } - } else { - pseudoHeadersEnded = true; - if (!Utils.isValidName(n)) { - throw newException("Bad header name '%s'", n); - } - } - String v = value.toString(); - if (!Utils.isValidValue(v)) { - throw newException("Bad header value '%s'", v); - } - } - - private UncheckedIOException newException(String message, String header) - { - return new UncheckedIOException( - new IOException(String.format(message, header))); - } - } - static final class ConnectionWindowUpdateSender extends WindowUpdateSender { final int initialWindowSize; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java index 942502d806f..cb0c018b961 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpClientImpl.java @@ -34,6 +34,7 @@ import java.net.Authenticator; import java.net.ConnectException; import java.net.CookieHandler; +import java.net.ProtocolException; import java.net.ProxySelector; import java.net.http.HttpConnectTimeoutException; import java.net.http.HttpTimeoutException; @@ -561,6 +562,10 @@ private void debugCompleted(String tag, long startNanos, HttpRequest req) { ConnectException ce = new ConnectException(msg); ce.initCause(throwable); throw ce; + } else if (throwable instanceof ProtocolException) { + ProtocolException pe = new ProtocolException(msg); + pe.initCause(throwable); + throw pe; } else if (throwable instanceof IOException) { throw new IOException(msg, throwable); } else { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java index a7a34e9e165..4f9d3cf56f0 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/HttpRequestImpl.java @@ -272,10 +272,10 @@ public HttpHeaders headers() { InetSocketAddress authority() { return authority; } - void setH2Upgrade(Http2ClientImpl h2client) { + void setH2Upgrade(Exchange exchange) { systemHeadersBuilder.setHeader("Connection", "Upgrade, HTTP2-Settings"); systemHeadersBuilder.setHeader("Upgrade", "h2c"); - systemHeadersBuilder.setHeader("HTTP2-Settings", h2client.getSettingsString()); + systemHeadersBuilder.setHeader("HTTP2-Settings", exchange.h2cSettingsStrings()); } @Override diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java index 364c695f0b2..b625f035f2f 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseBodyHandlers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -35,6 +35,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.util.List; +import java.util.Objects; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentMap; import java.util.function.Function; @@ -123,16 +124,21 @@ public void applyPushPromise( if (!initiatingURI.getHost().equalsIgnoreCase(pushRequestURI.getHost())) return; + String initiatingScheme = initiatingURI.getScheme(); + String pushRequestScheme = pushRequestURI.getScheme(); + + if (!initiatingScheme.equalsIgnoreCase(pushRequestScheme)) return; + int initiatingPort = initiatingURI.getPort(); if (initiatingPort == -1 ) { - if ("https".equalsIgnoreCase(initiatingURI.getScheme())) + if ("https".equalsIgnoreCase(initiatingScheme)) initiatingPort = 443; else initiatingPort = 80; } int pushPort = pushRequestURI.getPort(); if (pushPort == -1 ) { - if ("https".equalsIgnoreCase(pushRequestURI.getScheme())) + if ("https".equalsIgnoreCase(pushRequestScheme)) pushPort = 443; else pushPort = 80; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java b/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java index 608c572722a..ecb3badde71 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/SocketTube.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -246,7 +246,7 @@ public final void handle() { } @Override public final void abort(IOException error) { - debug().log(() -> "abort: " + error); + debug().log(() -> this.getClass().getSimpleName() + " abort: " + error); pause(); // pause, then signal signalError(error); // should not be resumed after abort (not checked) } @@ -724,10 +724,12 @@ public final void request(long n) { @Override public final void cancel() { pauseReadEvent(); + if (debug.on()) debug.log("Read subscription cancelled"); if (Log.channel()) { Log.logChannel("Read subscription cancelled for channel {0}", channelDescr()); } + if (debug.on()) debug.log("Stopping read scheduler"); readScheduler.stop(); } @@ -748,6 +750,7 @@ final void handleError() { } final void signalError(Throwable error) { + if (debug.on()) debug.log("signal read error: " + error); if (!errorRef.compareAndSet(null, error)) { return; } @@ -808,6 +811,7 @@ final void read() { } current.errorRef.compareAndSet(null, error); current.signalCompletion(); + if (debug.on()) debug.log("Stopping read scheduler"); readScheduler.stop(); debugState("leaving read() loop with error: "); return; @@ -831,6 +835,7 @@ final void read() { // anyway. pauseReadEvent(); current.signalCompletion(); + if (debug.on()) debug.log("Stopping read scheduler"); readScheduler.stop(); } debugState("leaving read() loop after EOF: "); @@ -850,6 +855,7 @@ final void read() { // waiting for this event to terminate. // So resume the read event and return now... resumeReadEvent(); + if (errorRef.get() != null) continue; debugState("leaving read() loop after onNext: "); return; } else { @@ -861,6 +867,7 @@ final void read() { // readable again. demand.increase(1); resumeReadEvent(); + if (errorRef.get() != null) continue; debugState("leaving read() loop with no bytes"); return; } @@ -879,6 +886,7 @@ final void read() { // Trying to pause the event here would actually // introduce a race condition between this loop and // request(n). + if (errorRef.get() != null) continue; debugState("leaving read() loop with no demand"); break; } @@ -946,6 +954,7 @@ protected final void signalEvent() { @Override protected final void signalError(Throwable error) { + if (debug.on()) debug.log("signalError to %s (%s)", sub, error); sub.signalError(error); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java index fb4a4dab173..f97632c12a1 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2023, 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 @@ -28,6 +28,9 @@ import java.io.EOFException; import java.io.IOException; import java.io.UncheckedIOException; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.VarHandle; +import java.net.ProtocolException; import java.net.URI; import java.nio.ByteBuffer; import java.util.ArrayList; @@ -40,6 +43,7 @@ import java.util.concurrent.Flow; import java.util.concurrent.Flow.Subscription; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; import java.util.function.BiPredicate; import java.net.http.HttpClient; @@ -47,10 +51,13 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodySubscriber; + import jdk.internal.net.http.common.*; import jdk.internal.net.http.frame.*; import jdk.internal.net.http.hpack.DecodingCallback; +import static jdk.internal.net.http.Exchange.MAX_NON_FINAL_RESPONSES; + /** * Http/2 Stream handling. * @@ -134,12 +141,22 @@ class Stream extends ExchangeImpl { private volatile boolean remotelyClosed; private volatile boolean closed; private volatile boolean endStreamSent; + private volatile boolean finalResponseCodeReceived; + private volatile boolean trailerReceived; + private AtomicInteger nonFinalResponseCount = new AtomicInteger(); - final AtomicBoolean deRegistered = new AtomicBoolean(false); + // Indicates the first reason that was invoked when sending a ResetFrame + // to the server. A streamState of 0 indicates that no reset was sent. + // (see markStream(int code) + private volatile int streamState; // assigned using STREAM_STATE varhandle. + private volatile boolean deRegistered; // assigned using DEREGISTERED varhandle. // state flags private boolean requestSent, responseReceived; + // send lock: prevent sending DataFrames after reset occurred. + private final Object sendLock = new Object(); + /** * A reference to this Stream's connection Send Window controller. The * stream MUST acquire the appropriate amount of Send Window before @@ -293,7 +310,7 @@ private boolean consumed(DataFrame df) { } boolean deRegister() { - return deRegistered.compareAndSet(false, true); + return DEREGISTERED.compareAndSet(this, false, true); } @Override @@ -336,6 +353,36 @@ private void receiveResetFrame(ResetFrame frame) { sched.runOrSchedule(); } + /** + * Records the first reason which was invoked when sending a ResetFrame + * to the server in the streamState, and return the previous value + * of the streamState. This is an atomic operation. + * A possible use of this method would be to send a ResetFrame only + * if no previous reset frame has been sent. + * For instance:
    {@code
    +     *  if (markStream(ResetFrame.CANCEL) == 0) {
    +     *      connection.sendResetFrame(streamId, ResetFrame.CANCEL);
    +     *  }
    +     *  }
    + * @param code the reason code as per HTTP/2 protocol + * @return the previous value of the stream state. + */ + int markStream(int code) { + if (code == 0) return streamState; + synchronized (sendLock) { + return (int) STREAM_STATE.compareAndExchange(this, 0, code); + } + } + + private void sendDataFrame(DataFrame frame) { + synchronized (sendLock) { + // must not send DataFrame after reset. + if (streamState == 0) { + connection.sendDataFrame(frame); + } + } + } + // pushes entire response body into response subscriber // blocking when required by local or remote flow control CompletableFuture receiveData(BodySubscriber bodySubscriber, Executor executor) { @@ -392,20 +439,22 @@ CompletableFuture> sendBodyAsync() { */ void incoming(Http2Frame frame) throws IOException { if (debug.on()) debug.log("incoming: %s", frame); + var cancelled = closed || streamState != 0; if ((frame instanceof HeaderFrame)) { HeaderFrame hframe = (HeaderFrame)frame; if (hframe.endHeaders()) { Log.logTrace("handling response (streamid={0})", streamid); handleResponse(); - if (hframe.getFlag(HeaderFrame.END_STREAM)) { - if (debug.on()) debug.log("handling END_STREAM: %d", streamid); - receiveDataFrame(new DataFrame(streamid, DataFrame.END_STREAM, List.of())); - } + } + if (hframe.getFlag(HeaderFrame.END_STREAM)) { + if (debug.on()) debug.log("handling END_STREAM: %d", streamid); + receiveDataFrame(new DataFrame(streamid, DataFrame.END_STREAM, List.of())); } } else if (frame instanceof DataFrame) { - receiveDataFrame((DataFrame)frame); + if (cancelled) connection.dropDataFrame((DataFrame) frame); + else receiveDataFrame((DataFrame) frame); } else { - otherFrame(frame); + if (!cancelled) otherFrame(frame); } } @@ -432,32 +481,89 @@ DecodingCallback rspHeadersConsumer() { return rspHeadersConsumer; } + String checkInterimResponseCountExceeded() { + // this is also checked by Exchange - but tracking it here too provides + // a more informative message. + int count = nonFinalResponseCount.incrementAndGet(); + if (MAX_NON_FINAL_RESPONSES > 0 && (count < 0 || count > MAX_NON_FINAL_RESPONSES)) { + return String.format( + "Stream %s PROTOCOL_ERROR: too many interim responses received: %s > %s", + streamid, count, MAX_NON_FINAL_RESPONSES); + } + return null; + } + protected void handleResponse() throws IOException { HttpHeaders responseHeaders = responseHeadersBuilder.build(); - responseCode = (int)responseHeaders - .firstValueAsLong(":status") - .orElseThrow(() -> new IOException("no statuscode in response")); - response = new Response( - request, exchange, responseHeaders, connection(), - responseCode, HttpClient.Version.HTTP_2); + if (!finalResponseCodeReceived) { + try { + responseCode = (int) responseHeaders + .firstValueAsLong(":status") + .orElseThrow(() -> new ProtocolException(String.format( + "Stream %s PROTOCOL_ERROR: no status code in response", + streamid))); + } catch (ProtocolException cause) { + cancelImpl(cause, ResetFrame.PROTOCOL_ERROR); + rspHeadersConsumer.reset(); + return; + } + + String protocolErrorMsg = null; + // If informational code, response is partially complete + if (responseCode < 100 || responseCode > 199) { + this.finalResponseCodeReceived = true; + } else { + protocolErrorMsg = checkInterimResponseCountExceeded(); + } + + if (protocolErrorMsg != null) { + if (debug.on()) { + debug.log(protocolErrorMsg); + } + cancelImpl(new ProtocolException(protocolErrorMsg), ResetFrame.PROTOCOL_ERROR); + rspHeadersConsumer.reset(); + return; + } - /* TODO: review if needs to be removed - the value is not used, but in case `content-length` doesn't parse as - long, there will be NumberFormatException. If left as is, make sure - code up the stack handles NFE correctly. */ - responseHeaders.firstValueAsLong("content-length"); + response = new Response( + request, exchange, responseHeaders, connection(), + responseCode, HttpClient.Version.HTTP_2); - if (Log.headers()) { - StringBuilder sb = new StringBuilder("RESPONSE HEADERS:\n"); - Log.dumpHeaders(sb, " ", responseHeaders); - Log.logHeaders(sb.toString()); - } + /* TODO: review if needs to be removed + the value is not used, but in case `content-length` doesn't parse as + long, there will be NumberFormatException. If left as is, make sure + code up the stack handles NFE correctly. */ + responseHeaders.firstValueAsLong("content-length"); + + if (Log.headers()) { + StringBuilder sb = new StringBuilder("RESPONSE HEADERS:\n"); + Log.dumpHeaders(sb, " ", responseHeaders); + Log.logHeaders(sb.toString()); + } + + // this will clear the response headers + rspHeadersConsumer.reset(); - // this will clear the response headers - rspHeadersConsumer.reset(); + completeResponse(response); + } else { + if (Log.headers()) { + StringBuilder sb = new StringBuilder("TRAILING HEADERS:\n"); + Log.dumpHeaders(sb, " ", responseHeaders); + Log.logHeaders(sb.toString()); + } + if (trailerReceived) { + String protocolErrorMsg = String.format( + "Stream %s PROTOCOL_ERROR: trailers already received", streamid); + if (debug.on()) { + debug.log(protocolErrorMsg); + } + cancelImpl(new ProtocolException(protocolErrorMsg), ResetFrame.PROTOCOL_ERROR); + } + trailerReceived = true; + rspHeadersConsumer.reset(); + } - completeResponse(response); } void incoming_reset(ResetFrame frame) { @@ -734,6 +840,16 @@ CompletableFuture> sendHeadersAsync() { } else { requestContentLen = 0; } + + // At this point the stream doesn't have a streamid yet. + // It will be allocated if we send the request headers. + Throwable t = errorRef.get(); + if (t != null) { + if (debug.on()) debug.log("stream already cancelled, headers not sent: %s", (Object)t); + return MinimalFuture.failedFuture(t); + } + + // sending the headers will cause the allocation of the stream id OutgoingHeaders> f = headerFrame(requestContentLen); connection.sendFrame(f); CompletableFuture> cf = new MinimalFuture<>(); @@ -759,10 +875,17 @@ void completed() { // been already closed (or will be closed shortly after). } - void registerStream(int id) { - this.streamid = id; - connection.putStream(this, streamid); - if (debug.on()) debug.log("Registered stream %d", id); + boolean registerStream(int id, boolean registerIfCancelled) { + boolean cancelled = closed; + if (!cancelled || registerIfCancelled) { + this.streamid = id; + connection.putStream(this, streamid); + if (debug.on()) { + debug.log("Stream %d registered (cancelled: %b, registerIfCancelled: %b)", + streamid, cancelled, registerIfCancelled); + } + } + return !cancelled; } void signalWindowUpdate() { @@ -867,6 +990,7 @@ void trySend() { cancelImpl(t); return; } + int state = streamState; do { // handle COMPLETED; @@ -879,7 +1003,7 @@ else if (item == COMPLETED) { } // handle bytes to send downstream - while (item.hasRemaining()) { + while (item.hasRemaining() && state == 0) { if (debug.on()) debug.log("trySend: %d", item.remaining()); DataFrame df = getDataFrame(item); if (df == null) { @@ -897,6 +1021,7 @@ else if (item == COMPLETED) { + "Too many bytes in request body. Expected: " + contentLength + ", got: " + (contentLength - remainingContentLength); + assert streamid > 0; connection.resetStream(streamid, ResetFrame.PROTOCOL_ERROR); throw new IOException(msg); } else if (remainingContentLength == 0) { @@ -907,15 +1032,26 @@ else if (item == COMPLETED) { } else { assert !endStreamSent : "internal error, send data after END_STREAM flag"; } + if ((state = streamState) != 0) { + if (debug.on()) debug.log("trySend: cancelled: %s", String.valueOf(t)); + break; + } if (debug.on()) debug.log("trySend: sending: %d", df.getDataLength()); - connection.sendDataFrame(df); + sendDataFrame(df); } + if (state != 0) break; assert !item.hasRemaining(); ByteBuffer b = outgoing.removeFirst(); assert b == item; } while (outgoing.peekFirst() != null); + if (state != 0) { + t = errorRef.get(); + if (t == null) t = new IOException(ResetFrame.stringForCode(streamState)); + throw t; + } + if (debug.on()) debug.log("trySend: request 1"); subscription.request(1); } catch (Throwable ex) { @@ -982,7 +1118,7 @@ private DataFrame getEmptyEndStreamDataFrame() { /** * A List of responses relating to this stream. Normally there is only - * one response, but intermediate responses like 100 are allowed + * one response, but interim responses like 100 are allowed * and must be passed up to higher level before continuing. Deals with races * such as if responses are returned before the CFs get created by * getResponseAsync() @@ -1118,7 +1254,11 @@ CompletableFuture sendBodyImpl() { @Override void cancel() { - cancel(new IOException("Stream " + streamid + " cancelled")); + if ((streamid == 0)) { + cancel(new IOException("Stream cancelled before streamid assigned")); + } else { + cancel(new IOException("Stream " + streamid + " cancelled")); + } } void onSubscriptionError(Throwable t) { @@ -1139,6 +1279,16 @@ void cancel(IOException cause) { cancelImpl(cause); } + @Override + void onProtocolError(final IOException cause) { + if (debug.on()) { + debug.log("cancelling exchange on stream %d due to protocol error: %s", streamid, cause.getMessage()); + } + Log.logError("cancelling exchange on stream {0} due to protocol error: {1}\n", streamid, cause); + // send a RESET frame and close the stream + cancelImpl(cause, ResetFrame.PROTOCOL_ERROR); + } + void connectionClosing(Throwable cause) { Flow.Subscriber subscriber = responseSubscriber == null ? pendingResponseSubscriber : responseSubscriber; @@ -1150,10 +1300,18 @@ void connectionClosing(Throwable cause) { // This method sends a RST_STREAM frame void cancelImpl(Throwable e) { + cancelImpl(e, ResetFrame.CANCEL); + } + + void cancelImpl(final Throwable e, final int resetFrameErrCode) { errorRef.compareAndSet(null, e); - if (debug.on()) debug.log("cancelling stream {0}: {1}", streamid, e); + if (debug.on()) { + if (streamid == 0) debug.log("cancelling stream: %s", (Object)e); + else debug.log("cancelling stream %d: %s", streamid, e); + } if (Log.trace()) { - Log.logTrace("cancelling stream {0}: {1}\n", streamid, e); + if (streamid == 0) Log.logTrace("cancelling stream: {0}\n", e); + else Log.logTrace("cancelling stream {0}: {1}\n", streamid, e); } boolean closing; if (closing = !closed) { // assigning closing to !closed @@ -1176,14 +1334,15 @@ void cancelImpl(Throwable e) { } try { // will send a RST_STREAM frame - if (streamid != 0) { - connection.decrementStreamsCount(streamid); - e = Utils.getCompletionCause(e); - if (e instanceof EOFException) { + if (streamid != 0 && streamState == 0) { + final Throwable cause = Utils.getCompletionCause(e); + if (cause instanceof EOFException) { // read EOF: no need to try & send reset + connection.decrementStreamsCount(streamid); connection.closeStream(streamid); } else { - connection.resetStream(streamid, ResetFrame.CANCEL); + // no use to send CANCEL if already closed. + sendResetStreamFrame(resetFrameErrCode); } } } catch (Throwable ex) { @@ -1191,6 +1350,14 @@ void cancelImpl(Throwable e) { } } + void sendResetStreamFrame(final int resetFrameErrCode) { + // do not reset a stream until it has a streamid. + if (streamid > 0 && markStream(resetFrameErrCode) == 0) { + connection.resetStream(streamid, resetFrameErrCode); + } + close(); + } + // This method doesn't send any frame void close() { if (closed) return; @@ -1205,6 +1372,7 @@ void close() { } static class PushedStream extends Stream { + final Stream parent; final PushGroup pushGroup; // push streams need the response CF allocated up front as it is // given directly to user via the multi handler callback function. @@ -1212,17 +1380,19 @@ static class PushedStream extends Stream { CompletableFuture> responseCF; final HttpRequestImpl pushReq; HttpResponse.BodyHandler pushHandler; + private volatile boolean finalPushResponseCodeReceived; - PushedStream(PushGroup pushGroup, + PushedStream(Stream parent, + PushGroup pushGroup, Http2Connection connection, Exchange pushReq) { // ## no request body possible, null window controller super(connection, pushReq, null); + this.parent = parent; this.pushGroup = pushGroup; this.pushReq = pushReq.request(); this.pushCF = new MinimalFuture<>(); this.responseCF = new MinimalFuture<>(); - } CompletableFuture> responseCF() { @@ -1308,35 +1478,57 @@ void completeResponseExceptionally(Throwable t) { @Override protected void handleResponse() { HttpHeaders responseHeaders = responseHeadersBuilder.build(); - responseCode = (int)responseHeaders - .firstValueAsLong(":status") - .orElse(-1); - if (responseCode == -1) { - completeResponseExceptionally(new IOException("No status code")); - } + if (!finalPushResponseCodeReceived) { + responseCode = (int)responseHeaders + .firstValueAsLong(":status") + .orElse(-1); - this.response = new Response( - pushReq, exchange, responseHeaders, connection(), - responseCode, HttpClient.Version.HTTP_2); + if (responseCode == -1) { + cancelImpl(new ProtocolException("No status code"), ResetFrame.PROTOCOL_ERROR); + rspHeadersConsumer.reset(); + return; + } else if (responseCode >= 100 && responseCode < 200) { + String protocolErrorMsg = checkInterimResponseCountExceeded(); + if (protocolErrorMsg != null) { + cancelImpl(new ProtocolException(protocolErrorMsg), ResetFrame.PROTOCOL_ERROR); + rspHeadersConsumer.reset(); + return; + } + } - /* TODO: review if needs to be removed - the value is not used, but in case `content-length` doesn't parse - as long, there will be NumberFormatException. If left as is, make - sure code up the stack handles NFE correctly. */ - responseHeaders.firstValueAsLong("content-length"); + this.finalPushResponseCodeReceived = true; - if (Log.headers()) { - StringBuilder sb = new StringBuilder("RESPONSE HEADERS"); - sb.append(" (streamid=").append(streamid).append("):\n"); - Log.dumpHeaders(sb, " ", responseHeaders); - Log.logHeaders(sb.toString()); - } + this.response = new Response( + pushReq, exchange, responseHeaders, connection(), + responseCode, HttpClient.Version.HTTP_2); - rspHeadersConsumer.reset(); + /* TODO: review if needs to be removed + the value is not used, but in case `content-length` doesn't parse + as long, there will be NumberFormatException. If left as is, make + sure code up the stack handles NFE correctly. */ + responseHeaders.firstValueAsLong("content-length"); - // different implementations for normal streams and pushed streams - completeResponse(response); + if (Log.headers()) { + StringBuilder sb = new StringBuilder("RESPONSE HEADERS"); + sb.append(" (streamid=").append(streamid).append("):\n"); + Log.dumpHeaders(sb, " ", responseHeaders); + Log.logHeaders(sb.toString()); + } + + rspHeadersConsumer.reset(); + + // different implementations for normal streams and pushed streams + completeResponse(response); + } else { + if (Log.headers()) { + StringBuilder sb = new StringBuilder("TRAILING HEADERS"); + sb.append(" (streamid=").append(streamid).append("):\n"); + Log.dumpHeaders(sb, " ", responseHeaders); + Log.logHeaders(sb.toString()); + } + rspHeadersConsumer.reset(); + } } } @@ -1384,9 +1576,12 @@ final String dbgString() { return connection.dbgString() + "/Stream("+streamid+")"; } - private class HeadersConsumer extends Http2Connection.ValidatingHeadersConsumer { + private class HeadersConsumer extends ValidatingHeadersConsumer implements DecodingCallback { + + boolean maxHeaderListSizeReached; - void reset() { + @Override + public void reset() { super.reset(); responseHeadersBuilder.clear(); debug.log("Response builder cleared, ready to receive new headers."); @@ -1396,14 +1591,60 @@ void reset() { public void onDecoded(CharSequence name, CharSequence value) throws UncheckedIOException { - String n = name.toString(); - String v = value.toString(); - super.onDecoded(n, v); - responseHeadersBuilder.addHeader(n, v); - if (Log.headers() && Log.trace()) { - Log.logTrace("RECEIVED HEADER (streamid={0}): {1}: {2}", - streamid, n, v); + if (maxHeaderListSizeReached) { + return; + } + try { + String n = name.toString(); + String v = value.toString(); + super.onDecoded(n, v); + responseHeadersBuilder.addHeader(n, v); + if (Log.headers() && Log.trace()) { + Log.logTrace("RECEIVED HEADER (streamid={0}): {1}: {2}", + streamid, n, v); + } + } catch (UncheckedIOException uio) { + // reset stream: From RFC 9113, section 8.1 + // Malformed requests or responses that are detected MUST be + // treated as a stream error (Section 5.4.2) of type + // PROTOCOL_ERROR. + onProtocolError(uio.getCause()); } } + + @Override + protected String formatMessage(String message, String header) { + return "malformed response: " + super.formatMessage(message, header); + } + + @Override + public void onMaxHeaderListSizeReached(long size, int maxHeaderListSize) throws ProtocolException { + if (maxHeaderListSizeReached) return; + try { + DecodingCallback.super.onMaxHeaderListSizeReached(size, maxHeaderListSize); + } catch (ProtocolException cause) { + maxHeaderListSizeReached = true; + // If this is a push stream: cancel the parent. + if (Stream.this instanceof Stream.PushedStream) { + ((Stream.PushedStream)Stream.this).parent.onProtocolError(cause); + } + // cancel the stream, continue processing + onProtocolError(cause); + reset(); + } + } + } + + private static final VarHandle STREAM_STATE; + private static final VarHandle DEREGISTERED; + static { + try { + STREAM_STATE = MethodHandles.lookup() + .findVarHandle(Stream.class, "streamState", int.class); + DEREGISTERED = MethodHandles.lookup() + .findVarHandle(Stream.class, "deRegistered", boolean.class); + } catch (Exception x) { + throw new ExceptionInInitializerError(x); + } } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/HeaderDecoder.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/HeaderDecoder.java new file mode 100644 index 00000000000..d81f52e6630 --- /dev/null +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/HeaderDecoder.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2023, 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 jdk.internal.net.http.common; + +import java.net.http.HttpHeaders; + +public class HeaderDecoder extends ValidatingHeadersConsumer { + + private final HttpHeadersBuilder headersBuilder; + + public HeaderDecoder() { + this.headersBuilder = new HttpHeadersBuilder(); + } + + @Override + public void onDecoded(CharSequence name, CharSequence value) { + String n = name.toString(); + String v = value.toString(); + super.onDecoded(n, v); + addHeader(n, v); + } + + protected void addHeader(String name, String value) { + headersBuilder.addHeader(name, value); + } + + public HttpHeaders headers() { + return headersBuilder.build(); + } +} diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java index b4e4010cbfb..984e6214b3c 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java @@ -371,16 +371,21 @@ public static URLPermission permissionForServer(URI uri, } + private static final boolean[] LOWER_CASE_CHARS = new boolean[128]; + // ABNF primitives defined in RFC 7230 private static final boolean[] tchar = new boolean[256]; private static final boolean[] fieldvchar = new boolean[256]; static { - char[] allowedTokenChars = - ("!#$%&'*+-.^_`|~0123456789" + - "abcdefghijklmnopqrstuvwxyz" + - "ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); - for (char c : allowedTokenChars) { + char[] lcase = ("!#$%&'*+-.^_`|~0123456789" + + "abcdefghijklmnopqrstuvwxyz").toCharArray(); + for (char c : lcase) { + tchar[c] = true; + LOWER_CASE_CHARS[c] = true; + } + char[] ucase = ("ABCDEFGHIJKLMNOPQRSTUVWXYZ").toCharArray(); + for (char c : ucase) { tchar[c] = true; } for (char c = 0x21; c < 0xFF; c++) { @@ -389,6 +394,16 @@ public static URLPermission permissionForServer(URI uri, fieldvchar[0x7F] = false; // a little hole (DEL) in the range } + public static boolean isValidLowerCaseName(String token) { + for (int i = 0; i < token.length(); i++) { + char c = token.charAt(i); + if (c > 255 || !LOWER_CASE_CHARS[c]) { + return false; + } + } + return !token.isEmpty(); + } + /* * Validates a RFC 7230 field-name. */ @@ -500,6 +515,19 @@ public static int getIntegerProperty(String name, int defaultValue) { Integer.parseInt(System.getProperty(name, String.valueOf(defaultValue)))); } + public static int getIntegerNetProperty(String property, int min, int max, int defaultValue, boolean log) { + int value = Utils.getIntegerNetProperty(property, defaultValue); + // use default value if misconfigured + if (value < min || value > max) { + if (log && Log.errors()) { + Log.logError("Property value for {0}={1} not in [{2}..{3}]: " + + "using default={4}", property, value, min, max, defaultValue); + } + value = defaultValue; + } + return value; + } + public static SSLParameters copySSLParameters(SSLParameters p) { SSLParameters p1 = new SSLParameters(); p1.setAlgorithmConstraints(p.getAlgorithmConstraints()); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/ValidatingHeadersConsumer.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/ValidatingHeadersConsumer.java new file mode 100644 index 00000000000..db873cdb05e --- /dev/null +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/ValidatingHeadersConsumer.java @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2023, 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 jdk.internal.net.http.common; + +import java.io.IOException; +import java.io.UncheckedIOException; +import java.util.Set; + +/* + * Checks RFC 9113 rules (relaxed) compliance regarding pseudo-headers. + */ +public class ValidatingHeadersConsumer { + + private static final Set PSEUDO_HEADERS = + Set.of(":authority", ":method", ":path", ":scheme", ":status"); + + /** Used to check that if there are pseudo-headers, they go first */ + private boolean pseudoHeadersEnded; + + /** + * Called when END_HEADERS was received. This consumer may be invoked + * again after reset() is called, but for a whole new set of headers. + */ + public void reset() { + pseudoHeadersEnded = false; + } + + /** + * Called when a header field (name, value) pair has been decoded + * @param name the decoded name + * @param value the decoded value + * @throws UncheckedIOException if the name or value are illegal + */ + public void onDecoded(CharSequence name, CharSequence value) + throws UncheckedIOException + { + String n = name.toString(); + if (n.startsWith(":")) { + if (pseudoHeadersEnded) { + throw newException("Unexpected pseudo-header '%s'", n); + } else if (!PSEUDO_HEADERS.contains(n)) { + throw newException("Unknown pseudo-header '%s'", n); + } + } else { + pseudoHeadersEnded = true; + // RFC-9113, section 8.2.1 for HTTP/2 and RFC-9114, section 4.2 state that + // header name MUST be lowercase (and allowed characters) + if (!Utils.isValidLowerCaseName(n)) { + throw newException("Bad header name '%s'", n); + } + } + String v = value.toString(); + if (!Utils.isValidValue(v)) { + throw newException("Bad header value '%s'", v); + } + } + + protected String formatMessage(String message, String header) { + return String.format(message, header); + } + + protected UncheckedIOException newException(String message, String header) + { + return new UncheckedIOException( + new IOException(formatMessage(message, header))); + } +} diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Decoder.java b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Decoder.java index 370677b5e16..7f56e091fe1 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Decoder.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Decoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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,7 @@ import jdk.internal.net.http.hpack.HPACK.Logger; import java.io.IOException; +import java.net.ProtocolException; import java.nio.ByteBuffer; import java.util.List; import java.util.concurrent.atomic.AtomicLong; @@ -107,12 +108,16 @@ public final class Decoder { private final StringReader stringReader; private final StringBuilder name; private final StringBuilder value; + private final int maxHeaderListSize; + private final int maxIndexed; private int intValue; private boolean firstValueRead; private boolean firstValueIndex; private boolean nameHuffmanEncoded; private boolean valueHuffmanEncoded; private int capacity; + private long size; + private int indexed; /** * Constructs a {@code Decoder} with the specified initial capacity of the @@ -129,6 +134,31 @@ public final class Decoder { * if capacity is negative */ public Decoder(int capacity) { + this(capacity, 0, 0); + } + + /** + * Constructs a {@code Decoder} with the specified initial capacity of the + * header table, a max header list size, and a maximum number of literals + * with indexing per header section. + * + *

    The value of the capacity has to be agreed between decoder and encoder out-of-band, + * e.g. by a protocol that uses HPACK + * (see 4.2. Maximum Table Size). + * + * @param capacity + * a non-negative integer + * @param maxHeaderListSize + * a maximum value for the header list size. This is the uncompressed + * names size + uncompressed values size + 32 bytes per field line + * @param maxIndexed + * the maximum number of literal with indexing we're prepared to handle + * for a header field section + * + * @throws IllegalArgumentException + * if capacity is negative + */ + public Decoder(int capacity, int maxHeaderListSize, int maxIndexed) { id = DECODERS_IDS.incrementAndGet(); logger = HPACK.getLogger().subLogger("Decoder#" + id); if (logger.isLoggable(NORMAL)) { @@ -145,6 +175,8 @@ public Decoder(int capacity) { toString(), hashCode); }); } + this.maxHeaderListSize = maxHeaderListSize; + this.maxIndexed = maxIndexed; setMaxCapacity0(capacity); table = new SimpleHeaderTable(capacity, logger.subLogger("HeaderTable")); integerReader = new IntegerReader(); @@ -242,23 +274,26 @@ public void decode(ByteBuffer headerBlock, requireNonNull(consumer, "consumer"); if (logger.isLoggable(NORMAL)) { logger.log(NORMAL, () -> format("reading %s, end of header block? %s", - headerBlock, endOfHeaderBlock)); + headerBlock, endOfHeaderBlock)); } while (headerBlock.hasRemaining()) { proceed(headerBlock, consumer); } if (endOfHeaderBlock && state != State.READY) { logger.log(NORMAL, () -> format("unexpected end of %s representation", - state)); + state)); throw new IOException("Unexpected end of header block"); } + if (endOfHeaderBlock) { + size = indexed = 0; + } } private void proceed(ByteBuffer input, DecodingCallback action) throws IOException { switch (state) { case READY: - resumeReady(input); + resumeReady(input, action); break; case INDEXED: resumeIndexed(input, action); @@ -280,7 +315,7 @@ private void proceed(ByteBuffer input, DecodingCallback action) } } - private void resumeReady(ByteBuffer input) { + private void resumeReady(ByteBuffer input, DecodingCallback action) throws IOException { int b = input.get(input.position()) & 0xff; // absolute read State s = states.get(b); if (logger.isLoggable(EXTRA)) { @@ -301,6 +336,9 @@ private void resumeReady(ByteBuffer input) { } break; case LITERAL_WITH_INDEXING: + if (maxIndexed > 0 && ++indexed > maxIndexed) { + action.onMaxLiteralWithIndexingReached(indexed, maxIndexed); + } state = State.LITERAL_WITH_INDEXING; firstValueIndex = (b & 0b0011_1111) != 0; if (firstValueIndex) { @@ -327,6 +365,12 @@ private void resumeReady(ByteBuffer input) { } } + private void checkMaxHeaderListSize(long sz, DecodingCallback consumer) throws ProtocolException { + if (maxHeaderListSize > 0 && sz > maxHeaderListSize) { + consumer.onMaxHeaderListSizeReached(sz, maxHeaderListSize); + } + } + // 0 1 2 3 4 5 6 7 // +---+---+---+---+---+---+---+---+ // | 1 | Index (7+) | @@ -344,6 +388,8 @@ private void resumeIndexed(ByteBuffer input, DecodingCallback action) } try { SimpleHeaderTable.HeaderField f = getHeaderFieldAt(intValue); + size = size + 32 + f.name.length() + f.value.length(); + checkMaxHeaderListSize(size, action); action.onIndexed(intValue, f.name, f.value); } finally { state = State.READY; @@ -386,7 +432,7 @@ private SimpleHeaderTable.HeaderField getHeaderFieldAt(int index) // private void resumeLiteral(ByteBuffer input, DecodingCallback action) throws IOException { - if (!completeReading(input)) { + if (!completeReading(input, action)) { return; } try { @@ -397,6 +443,8 @@ private void resumeLiteral(ByteBuffer input, DecodingCallback action) intValue, value, valueHuffmanEncoded)); } SimpleHeaderTable.HeaderField f = getHeaderFieldAt(intValue); + size = size + 32 + f.name.length() + value.length(); + checkMaxHeaderListSize(size, action); action.onLiteral(intValue, f.name, value, valueHuffmanEncoded); } else { if (logger.isLoggable(NORMAL)) { @@ -404,6 +452,8 @@ private void resumeLiteral(ByteBuffer input, DecodingCallback action) "literal without indexing ('%s', huffman=%b, '%s', huffman=%b)", name, nameHuffmanEncoded, value, valueHuffmanEncoded)); } + size = size + 32 + name.length() + value.length(); + checkMaxHeaderListSize(size, action); action.onLiteral(name, nameHuffmanEncoded, value, valueHuffmanEncoded); } } finally { @@ -437,7 +487,7 @@ private void resumeLiteral(ByteBuffer input, DecodingCallback action) private void resumeLiteralWithIndexing(ByteBuffer input, DecodingCallback action) throws IOException { - if (!completeReading(input)) { + if (!completeReading(input, action)) { return; } try { @@ -457,6 +507,8 @@ private void resumeLiteralWithIndexing(ByteBuffer input, } SimpleHeaderTable.HeaderField f = getHeaderFieldAt(intValue); n = f.name; + size = size + 32 + n.length() + v.length(); + checkMaxHeaderListSize(size, action); action.onLiteralWithIndexing(intValue, n, v, valueHuffmanEncoded); } else { n = name.toString(); @@ -465,6 +517,8 @@ private void resumeLiteralWithIndexing(ByteBuffer input, "literal with incremental indexing ('%s', huffman=%b, '%s', huffman=%b)", n, nameHuffmanEncoded, value, valueHuffmanEncoded)); } + size = size + 32 + n.length() + v.length(); + checkMaxHeaderListSize(size, action); action.onLiteralWithIndexing(n, nameHuffmanEncoded, v, valueHuffmanEncoded); } table.put(n, v); @@ -498,7 +552,7 @@ private void resumeLiteralWithIndexing(ByteBuffer input, private void resumeLiteralNeverIndexed(ByteBuffer input, DecodingCallback action) throws IOException { - if (!completeReading(input)) { + if (!completeReading(input, action)) { return; } try { @@ -509,6 +563,8 @@ private void resumeLiteralNeverIndexed(ByteBuffer input, intValue, value, valueHuffmanEncoded)); } SimpleHeaderTable.HeaderField f = getHeaderFieldAt(intValue); + size = size + 32 + f.name.length() + value.length(); + checkMaxHeaderListSize(size, action); action.onLiteralNeverIndexed(intValue, f.name, value, valueHuffmanEncoded); } else { if (logger.isLoggable(NORMAL)) { @@ -516,6 +572,8 @@ private void resumeLiteralNeverIndexed(ByteBuffer input, "literal never indexed ('%s', huffman=%b, '%s', huffman=%b)", name, nameHuffmanEncoded, value, valueHuffmanEncoded)); } + size = size + 32 + name.length() + value.length(); + checkMaxHeaderListSize(size, action); action.onLiteralNeverIndexed(name, nameHuffmanEncoded, value, valueHuffmanEncoded); } } finally { @@ -553,7 +611,7 @@ private void resumeSizeUpdate(ByteBuffer input, } } - private boolean completeReading(ByteBuffer input) throws IOException { + private boolean completeReading(ByteBuffer input, DecodingCallback action) throws IOException { if (!firstValueRead) { if (firstValueIndex) { if (!integerReader.read(input)) { @@ -563,6 +621,8 @@ private boolean completeReading(ByteBuffer input) throws IOException { integerReader.reset(); } else { if (!stringReader.read(input, name)) { + long sz = size + 32 + name.length(); + checkMaxHeaderListSize(sz, action); return false; } nameHuffmanEncoded = stringReader.isHuffmanEncoded(); @@ -572,6 +632,8 @@ private boolean completeReading(ByteBuffer input) throws IOException { return false; } else { if (!stringReader.read(input, value)) { + long sz = size + 32 + name.length() + value.length(); + checkMaxHeaderListSize(sz, action); return false; } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/DecodingCallback.java b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/DecodingCallback.java index 5e9df860feb..228f9bf0206 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/DecodingCallback.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/DecodingCallback.java @@ -24,6 +24,7 @@ */ package jdk.internal.net.http.hpack; +import java.net.ProtocolException; import java.nio.ByteBuffer; /** @@ -292,4 +293,17 @@ default void onLiteralWithIndexing(CharSequence name, * new capacity of the header table */ default void onSizeUpdate(int capacity) { } + + default void onMaxHeaderListSizeReached(long size, int maxHeaderListSize) + throws ProtocolException { + throw new ProtocolException(String + .format("Size exceeds MAX_HEADERS_LIST_SIZE: %s > %s", + size, maxHeaderListSize)); + } + + default void onMaxLiteralWithIndexingReached(long indexed, int maxIndexed) + throws ProtocolException { + throw new ProtocolException(String.format("Too many literal with indexing: %s > %s", + indexed, maxIndexed)); + } } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Encoder.java b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Encoder.java index 4188937b1ad..c603e917ca4 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Encoder.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/hpack/Encoder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -258,9 +258,10 @@ public void header(CharSequence name, } } } + assert encoding : "encoding is false"; } - private boolean isHuffmanBetterFor(CharSequence value) { + protected final boolean isHuffmanBetterFor(CharSequence value) { // prefer Huffman encoding only if it is strictly smaller than Latin-1 return huffmanWriter.lengthOf(value) < value.length(); } @@ -340,6 +341,10 @@ protected int calculateCapacity(int maxCapacity) { return 0; } + protected final int tableIndexOf(CharSequence name, CharSequence value) { + return getHeaderTable().indexOf(name, value); + } + /** * Encodes the {@linkplain #header(CharSequence, CharSequence) set up} * header into the given buffer. @@ -380,6 +385,7 @@ public final boolean encode(ByteBuffer headerBlock) { writer.reset(); // FIXME: WHY? encoding = false; } + assert done || encoding : "done: " + done + ", encoding: " + encoding; return done; } @@ -542,4 +548,8 @@ protected final void checkEncoding() { // TODO: better name e.g. checkIfEncoding "Previous encoding operation hasn't finished yet"); } } + + protected final Logger logger() { + return logger; + } } diff --git a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/EncryptionKey.java b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/EncryptionKey.java index 0c75b905044..593a5a42a5c 100644 --- a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/EncryptionKey.java +++ b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/EncryptionKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -168,7 +168,7 @@ public String toString() { if (destroyed) { return "Destroyed EncryptionKey"; } - return "key " + key.toString(); + return "EncryptionKey: " + key.toString(); } /** diff --git a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosCredMessage.java b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosCredMessage.java index 27c2741d911..a94e5777789 100644 --- a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosCredMessage.java +++ b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosCredMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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,7 +27,6 @@ import javax.security.auth.Destroyable; import java.util.Arrays; -import java.util.Base64; import java.util.Objects; /** @@ -140,8 +139,7 @@ public String toString() { if (destroyed) { return "Destroyed KerberosCredMessage"; } else { - return "KRB_CRED from " + sender + " to " + recipient + ":\n" - + Base64.getUrlEncoder().encodeToString(message); + return "KRB_CRED from " + sender + " to " + recipient; } } diff --git a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosKey.java b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosKey.java index 49a9b5f6481..67a9e0ad4b2 100644 --- a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosKey.java +++ b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KerberosKey.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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 @@ -270,9 +270,9 @@ public String toString() { if (destroyed) { return "Destroyed KerberosKey"; } - return "Kerberos Principal " + principal + - "Key Version " + versionNum + - "key " + key.toString(); + return "KerberosKey: principal " + principal + + ", version " + versionNum + + ", key " + key.toString(); } /** diff --git a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java index 05194ae1364..914e7cb2907 100644 --- a/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java +++ b/src/java.security.jgss/share/classes/javax/security/auth/kerberos/KeyImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2024, 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,7 +30,8 @@ import javax.crypto.SecretKey; import javax.security.auth.Destroyable; import javax.security.auth.DestroyFailedException; -import sun.security.util.HexDumpEncoder; + +import sun.security.jgss.krb5.Krb5Util; import sun.security.krb5.Asn1Exception; import sun.security.krb5.PrincipalName; import sun.security.krb5.EncryptionKey; @@ -210,15 +211,8 @@ private void readObject(ObjectInputStream ois) } public String toString() { - HexDumpEncoder hd = new HexDumpEncoder(); - return "EncryptionKey: keyType=" + keyType - + " keyBytes (hex dump)=" - + (keyBytes == null || keyBytes.length == 0 ? - " Empty Key" : - '\n' + hd.encodeBuffer(keyBytes) - + '\n'); - - + return "keyType=" + keyType + + ", " + Krb5Util.keyInfo(keyBytes); } public int hashCode() { diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java index fef1ac2a385..6a19c6b967f 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Context.java @@ -909,15 +909,11 @@ public final int getWrapSizeLimit(int qop, boolean confReq, public final byte[] wrap(byte[] inBuf, int offset, int len, MessageProp msgProp) throws GSSException { - if (DEBUG) { - System.out.println("Krb5Context.wrap: data=[" - + getHexBytes(inBuf, offset, len) - + "]"); - } - if (state != STATE_DONE) - throw new GSSException(GSSException.NO_CONTEXT, -1, - "Wrap called in invalid state!"); + if (state != STATE_DONE) { + throw new GSSException(GSSException.NO_CONTEXT, -1, + "Wrap called in invalid state!"); + } byte[] encToken = null; try { @@ -1062,12 +1058,6 @@ public final byte[] unwrap(byte[] inBuf, int offset, int len, setSequencingAndReplayProps(token, msgProp); } - if (DEBUG) { - System.out.println("Krb5Context.unwrap: data=[" - + getHexBytes(data, 0, data.length) - + "]"); - } - return data; } @@ -1416,8 +1406,8 @@ public byte[] getEncoded() { @Override public String toString() { - return "Kerberos session key: etype: " + key.getEType() + "\n" + - new HexDumpEncoder().encodeBuffer(key.getBytes()); + return "Kerberos session key: etype=" + key.getEType() + + ", " + Krb5Util.keyInfo(key.getBytes()); } } diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Util.java b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Util.java index 387edd76691..86fdaefbb37 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Util.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/krb5/Krb5Util.java @@ -301,4 +301,19 @@ public static EncryptionKey[] keysFromJavaxKeyTab( KeyTab ktab, PrincipalName cname) { return snapshotFromJavaxKeyTab(ktab).readServiceKeys(cname); } + + public static String keyInfo(byte[] data) { + if (data == null) { + return "null key"; + } else if (data.length == 0) { + return "empty key"; + } else { + for (byte b : data) { + if (b != 0) { + return data.length + "-byte key"; + } + } + return data.length + "-byte zero key"; + } + } } diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/EncryptionKey.java b/src/java.security.jgss/share/classes/sun/security/krb5/EncryptionKey.java index dc51f8b51fc..a15e4e85b36 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/EncryptionKey.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/EncryptionKey.java @@ -31,6 +31,7 @@ package sun.security.krb5; +import sun.security.jgss.krb5.Krb5Util; import sun.security.util.*; import sun.security.krb5.internal.*; import sun.security.krb5.internal.crypto.*; @@ -498,12 +499,7 @@ public synchronized void writeKey(CCacheOutputStream cos) public String toString() { return new String("EncryptionKey: keyType=" + keyType - + " kvno=" + kvno - + " keyValue (hex dump)=" - + (keyValue == null || keyValue.length == 0 ? - " Empty Key" : '\n' - + Krb5.hexDumper.encodeBuffer(keyValue) - + '\n')); + + ", kvno=" + kvno + ", " + Krb5Util.keyInfo(keyValue)); } /** diff --git a/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java b/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java index d0ebcc3f36b..436ed7564cc 100644 --- a/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java +++ b/src/java.security.jgss/share/classes/sun/security/krb5/internal/Krb5.java @@ -313,8 +313,6 @@ public static String getErrorMessage(int i) { public static final boolean DEBUG = java.security.AccessController.doPrivileged( new sun.security.action.GetBooleanAction("sun.security.krb5.debug")); - public static final sun.security.util.HexDumpEncoder hexDumper = - new sun.security.util.HexDumpEncoder(); static { errMsgList = new Hashtable (); diff --git a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Kinit.java b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Kinit.java index 813939643c3..4f124771d51 100644 --- a/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Kinit.java +++ b/src/java.security.jgss/windows/classes/sun/security/krb5/internal/tools/Kinit.java @@ -192,10 +192,6 @@ private void acquire() System.out.print("Password for " + princName + ":"); System.out.flush(); psswd = Password.readPassword(System.in); - if (DEBUG) { - System.out.println(">>> Kinit console input " + - new String(psswd)); - } } builder = new KrbAsReqBuilder(principal, psswd); } else { diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/SchemaDVFactory.java b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/SchemaDVFactory.java index f81b7cf41ee..85d4ac0a50c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/SchemaDVFactory.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/SchemaDVFactory.java @@ -53,7 +53,7 @@ public abstract class SchemaDVFactory { * @exception DVFactoryException cannot create an instance of the specified * class name or the default class name */ - public static synchronized final SchemaDVFactory getInstance() throws DVFactoryException { + public static final SchemaDVFactory getInstance() throws DVFactoryException { return getInstance(DEFAULT_FACTORY_CLASS); } //getInstance(): SchemaDVFactory @@ -66,7 +66,7 @@ public static synchronized final SchemaDVFactory getInstance() throws DVFactoryE * @exception DVFactoryException cannot create an instance of the specified * class name or the default class name */ - public static synchronized final SchemaDVFactory getInstance(String factoryClass) throws DVFactoryException { + public static final SchemaDVFactory getInstance(String factoryClass) throws DVFactoryException { try { // if the class name is not specified, use the default one @@ -78,7 +78,7 @@ public static synchronized final SchemaDVFactory getInstance(String factoryClass } // can't create a new object of this class - protected SchemaDVFactory(){} + protected SchemaDVFactory() {} /** * Get a built-in simple type of the given name diff --git a/src/jdk.accessibility/windows/native/libjavaaccessbridge/AccessBridgeJavaEntryPoints.cpp b/src/jdk.accessibility/windows/native/libjavaaccessbridge/AccessBridgeJavaEntryPoints.cpp index 5386e4afdd3..c16fd791e5b 100644 --- a/src/jdk.accessibility/windows/native/libjavaaccessbridge/AccessBridgeJavaEntryPoints.cpp +++ b/src/jdk.accessibility/windows/native/libjavaaccessbridge/AccessBridgeJavaEntryPoints.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -82,6 +82,22 @@ AccessBridgeJavaEntryPoints::~AccessBridgeJavaEntryPoints() { return (returnVal); \ } +#define EXCEPTION_CHECK_WITH_RELEASE(situationDescription, returnVal, js, stringBytes) \ + if (exception = jniEnv->ExceptionOccurred()) { \ + PrintDebugString("[ERROR]: *** Exception occured while doing: %s - call to GetStringLength; returning %d", situationDescription, returnVal); \ + jniEnv->ExceptionDescribe(); \ + jniEnv->ExceptionClear(); \ + jniEnv->ReleaseStringChars(js, stringBytes); \ + return (returnVal); \ + } \ + jniEnv->ReleaseStringChars(js, stringBytes); \ + if (exception = jniEnv->ExceptionOccurred()) { \ + PrintDebugString("[ERROR]: *** Exception occured while doing: %s - call to ReleaseStringChars; returning %d", situationDescription, returnVal); \ + jniEnv->ExceptionDescribe(); \ + jniEnv->ExceptionClear(); \ + return (returnVal); \ + } + #define EXCEPTION_CHECK_VOID(situationDescription) \ if (exception = jniEnv->ExceptionOccurred()) { \ PrintDebugString("[ERROR]: *** Exception occured while doing: %s", situationDescription); \ @@ -1215,9 +1231,7 @@ AccessBridgeJavaEntryPoints::getVirtualAccessibleName ( EXCEPTION_CHECK("Getting AccessibleName - call to GetStringChars()", FALSE); wcsncpy(name, stringBytes, nameSize - 1); length = jniEnv->GetStringLength(js); - EXCEPTION_CHECK("Getting AccessibleName - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleName - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleName", FALSE, js, stringBytes); jniEnv->CallVoidMethod ( accessBridgeObject, decrementReferenceMethod, js); @@ -1380,9 +1394,7 @@ AccessBridgeJavaEntryPoints::getTextAttributesInRange(const jobject accessibleCo length = jniEnv->GetStringLength(js); test_attributes.fullAttributesString[length < (sizeof(test_attributes.fullAttributesString) / sizeof(wchar_t)) ? length : (sizeof(test_attributes.fullAttributesString) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleAttributesAtIndex - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleAttributesAtIndex - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleAttributesAtIndex", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleAttributesAtIndex - call to CallVoidMethod()", FALSE); @@ -1735,11 +1747,9 @@ AccessBridgeJavaEntryPoints::getAccessibleContextInfo(jobject accessibleContext, EXCEPTION_CHECK("Getting AccessibleName - call to GetStringChars()", FALSE); wcsncpy(info->name, stringBytes, (sizeof(info->name) / sizeof(wchar_t))); length = jniEnv->GetStringLength(js); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleName", FALSE, js, stringBytes); info->name[length < (sizeof(info->name) / sizeof(wchar_t)) ? length : (sizeof(info->name) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleName - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleName - call to ReleaseStringChars()", FALSE); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleName - call to CallVoidMethod()", FALSE); @@ -1767,11 +1777,9 @@ AccessBridgeJavaEntryPoints::getAccessibleContextInfo(jobject accessibleContext, EXCEPTION_CHECK("Getting AccessibleName - call to GetStringChars()", FALSE); wcsncpy(info->description, stringBytes, (sizeof(info->description) / sizeof(wchar_t))); length = jniEnv->GetStringLength(js); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleName", FALSE, js, stringBytes); info->description[length < (sizeof(info->description) / sizeof(wchar_t)) ? length : (sizeof(info->description) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleName - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleName - call to ReleaseStringChars()", FALSE); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleName - call to CallVoidMethod()", FALSE); @@ -1799,11 +1807,9 @@ AccessBridgeJavaEntryPoints::getAccessibleContextInfo(jobject accessibleContext, EXCEPTION_CHECK("Getting AccessibleRole - call to GetStringChars()", FALSE); wcsncpy(info->role, stringBytes, (sizeof(info->role) / sizeof(wchar_t))); length = jniEnv->GetStringLength(js); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleRole", FALSE, js, stringBytes); info->role[length < (sizeof(info->role) / sizeof(wchar_t)) ? length : (sizeof(info->role) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleRole - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleRole - call to ReleaseStringChars()", FALSE); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleRole - call to CallVoidMethod()", FALSE); @@ -1831,11 +1837,9 @@ AccessBridgeJavaEntryPoints::getAccessibleContextInfo(jobject accessibleContext, EXCEPTION_CHECK("Getting AccessibleRole_en_US - call to GetStringChars()", FALSE); wcsncpy(info->role_en_US, stringBytes, (sizeof(info->role_en_US) / sizeof(wchar_t))); length = jniEnv->GetStringLength(js); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleRole_en_US", FALSE, js, stringBytes); info->role_en_US[length < (sizeof(info->role_en_US) / sizeof(wchar_t)) ? length : (sizeof(info->role_en_US) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleRole_en_US - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleRole_en_US - call to ReleaseStringChars()", FALSE); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleRole_en_US - call to CallVoidMethod()", FALSE); @@ -1862,11 +1866,9 @@ AccessBridgeJavaEntryPoints::getAccessibleContextInfo(jobject accessibleContext, EXCEPTION_CHECK("Getting AccessibleState - call to GetStringChars()", FALSE); wcsncpy(info->states, stringBytes, (sizeof(info->states) / sizeof(wchar_t))); length = jniEnv->GetStringLength(js); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleState", FALSE, js, stringBytes); info->states[length < (sizeof(info->states) / sizeof(wchar_t)) ? length : (sizeof(info->states) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleState - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleState - call to ReleaseStringChars()", FALSE); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleState - call to CallVoidMethod()", FALSE); @@ -1893,11 +1895,9 @@ AccessBridgeJavaEntryPoints::getAccessibleContextInfo(jobject accessibleContext, EXCEPTION_CHECK("Getting AccessibleState_en_US - call to GetStringChars()", FALSE); wcsncpy(info->states_en_US, stringBytes, (sizeof(info->states_en_US) / sizeof(wchar_t))); length = jniEnv->GetStringLength(js); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleState_en_US", FALSE, js, stringBytes); info->states_en_US[length < (sizeof(info->states_en_US) / sizeof(wchar_t)) ? length : (sizeof(info->states_en_US) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleState_en_US - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleState_en_US - call to ReleaseStringChars()", FALSE); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleState_en_US - call to CallVoidMethod()", FALSE); @@ -2809,11 +2809,9 @@ AccessBridgeJavaEntryPoints::getAccessibleRelationSet(jobject accessibleContext, EXCEPTION_CHECK("Getting AccessibleRelation key - call to GetStringChars()", FALSE); wcsncpy(relationSet->relations[i].key, stringBytes, (sizeof(relationSet->relations[i].key ) / sizeof(wchar_t))); length = jniEnv->GetStringLength(js); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleRelation key", FALSE, js, stringBytes); relationSet->relations[i].key [length < (sizeof(relationSet->relations[i].key ) / sizeof(wchar_t)) ? length : (sizeof(relationSet->relations[i].key ) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleRelation key - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleRelation key - call to ReleaseStringChars()", FALSE); // jniEnv->CallVoidMethod(accessBridgeObject, // decrementReferenceMethod, js); //EXCEPTION_CHECK("Getting AccessibleRelation key - call to CallVoidMethod()", FALSE); @@ -2915,9 +2913,7 @@ AccessBridgeJavaEntryPoints::getAccessibleHypertext(jobject accessibleContext, length = (sizeof(hypertext->links[i].text) / sizeof(wchar_t)) - 2; } hypertext->links[i].text[length] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleHyperlink text - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleHyperlink text - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleHyperlink text", FALSE, js, stringBytes); // jniEnv->CallVoidMethod(accessBridgeObject, // decrementReferenceMethod, js); //EXCEPTION_CHECK("Getting AccessibleHyperlink text - call to CallVoidMethod()", FALSE); @@ -3052,9 +3048,7 @@ AccessBridgeJavaEntryPoints::getAccessibleHypertextExt(const jobject accessibleC length = (sizeof(hypertext->links[bufIndex].text) / sizeof(wchar_t)) - 2; } hypertext->links[bufIndex].text[length] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleHyperlink text - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleHyperlink text - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleHyperlink text", FALSE, js, stringBytes); // jniEnv->CallVoidMethod(accessBridgeObject, // decrementReferenceMethod, js); //EXCEPTION_CHECK("Getting AccessibleHyperlink text - call to CallVoidMethod()", FALSE); @@ -3171,9 +3165,7 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleHyperlink(jobject hypertext, length = (sizeof(info->text) / sizeof(wchar_t)) - 2; } info->text[length] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleHyperlink text - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleHyperlink text - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleHyperlink text", FALSE, js, stringBytes); // jniEnv->CallVoidMethod(accessBridgeObject, // decrementReferenceMethod, js); //EXCEPTION_CHECK("Getting AccessibleHyperlink text - call to CallVoidMethod()", FALSE); @@ -3300,9 +3292,7 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleIcons(jobject accessibleContext, length = (sizeof(icons->iconInfo[i].description) / sizeof(wchar_t)) - 2; } icons->iconInfo[i].description[length] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleIcon description - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleIcon description - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleIcon description", FALSE, js, stringBytes); // jniEnv->CallVoidMethod(accessBridgeObject, // decrementReferenceMethod, js); //EXCEPTION_CHECK("Getting AccessibleIcon description - call to CallVoidMethod()", FALSE); @@ -3379,9 +3369,7 @@ BOOL AccessBridgeJavaEntryPoints::getAccessibleActions(jobject accessibleContext length = (sizeof(actions->actionInfo[i].name ) / sizeof(wchar_t)) - 2; } actions->actionInfo[i].name [length] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleAction name - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleAction name - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleAction name", FALSE, js, stringBytes); // jniEnv->CallVoidMethod(accessBridgeObject, // decrementReferenceMethod, js); //EXCEPTION_CHECK("Getting AccessibleAction name - call to CallVoidMethod()", FALSE); @@ -3561,9 +3549,7 @@ AccessBridgeJavaEntryPoints::getAccessibleTextItems(jobject accessibleContext, length = jniEnv->GetStringLength(js); textItems->word[length < (sizeof(textItems->word) / sizeof(wchar_t)) ? length : (sizeof(textItems->word) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleWordAtIndex - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleWordAtIndex - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleWordAtIndex", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleWordAtIndex - call to CallVoidMethod()", FALSE); @@ -3597,9 +3583,7 @@ AccessBridgeJavaEntryPoints::getAccessibleTextItems(jobject accessibleContext, } else { textItems->sentence[(sizeof(textItems->sentence) / sizeof(wchar_t))-2] = (wchar_t) 0; } - EXCEPTION_CHECK("Getting AccessibleSentenceAtIndex - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleSentenceAtIndex - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleSentenceAtIndex", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleSentenceAtIndex - call to CallVoidMethod()", FALSE); @@ -3673,9 +3657,7 @@ AccessBridgeJavaEntryPoints::getAccessibleTextSelectionInfo(jobject accessibleCo length = jniEnv->GetStringLength(js); selectionInfo->selectedText[length < (sizeof(selectionInfo->selectedText) / sizeof(wchar_t)) ? length : (sizeof(selectionInfo->selectedText) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleTextSelectedText - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleTextSelectedText - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleTextSelectedText", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleTextSelectedText - call to CallVoidMethod()", FALSE); @@ -3890,9 +3872,7 @@ AccessBridgeJavaEntryPoints::getAccessibleTextAttributes(jobject accessibleConte length = jniEnv->GetStringLength(js); attributes->backgroundColor[length < (sizeof(attributes->backgroundColor) / sizeof(wchar_t)) ? length : (sizeof(attributes->backgroundColor) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting BackgroundColorFromAttributeSet - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting BackgroundColorFromAttributeSet - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting BackgroundColorFromAttributeSet", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting BackgroundColorFromAttributeSet - call to CallVoidMethod()", FALSE); @@ -3927,9 +3907,7 @@ AccessBridgeJavaEntryPoints::getAccessibleTextAttributes(jobject accessibleConte length = jniEnv->GetStringLength(js); attributes->foregroundColor[length < (sizeof(attributes->foregroundColor) / sizeof(wchar_t)) ? length : (sizeof(attributes->foregroundColor) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting ForegroundColorFromAttributeSet - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting ForegroundColorFromAttributeSet - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting ForegroundColorFromAttributeSet", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting ForegroundColorFromAttributeSet - call to CallVoidMethod()", FALSE); @@ -3964,9 +3942,7 @@ AccessBridgeJavaEntryPoints::getAccessibleTextAttributes(jobject accessibleConte length = jniEnv->GetStringLength(js); attributes->fontFamily[length < (sizeof(attributes->fontFamily) / sizeof(wchar_t)) ? length : (sizeof(attributes->fontFamily) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting FontFamilyFromAttributeSet - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting FontFamilyFromAttributeSet - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting FontFamilyFromAttributeSet", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting FontFamilyFromAttributeSet - call to CallVoidMethod()", FALSE); @@ -4170,9 +4146,7 @@ AccessBridgeJavaEntryPoints::getAccessibleTextAttributes(jobject accessibleConte length = jniEnv->GetStringLength(js); attributes->fullAttributesString[length < (sizeof(attributes->fullAttributesString) / sizeof(wchar_t)) ? length : (sizeof(attributes->fullAttributesString) / sizeof(wchar_t))-2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting AccessibleAttributesAtIndex - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleAttributesAtIndex - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleAttributesAtIndex", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleAttributesAtIndex - call to CallVoidMethod()", FALSE); @@ -4413,9 +4387,7 @@ AccessBridgeJavaEntryPoints::getAccessibleTextRange(jobject accessibleContext, PrintDebugString("[INFO]: Accessible Text stringBytes length = %d", length); text[length < len ? length : len - 2] = (wchar_t) 0; wPrintDebugString(L"[INFO]: Accessible Text 'text' after null termination = %ls", text); - EXCEPTION_CHECK("Getting AccessibleTextRange - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting AccessibleTextRange - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting AccessibleTextRange", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting AccessibleTextRange - call to CallVoidMethod()", FALSE); @@ -4458,9 +4430,7 @@ AccessBridgeJavaEntryPoints::getCurrentAccessibleValueFromContext(jobject access wcsncpy(value, stringBytes, len); length = jniEnv->GetStringLength(js); value[length < len ? length : len - 2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting CurrentAccessibleValue - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting CurrentAccessibleValue - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting CurrentAccessibleValue", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting CurrentAccessibleValue - call to CallVoidMethod()", FALSE); @@ -4501,9 +4471,7 @@ AccessBridgeJavaEntryPoints::getMaximumAccessibleValueFromContext(jobject access wcsncpy(value, stringBytes, len); length = jniEnv->GetStringLength(js); value[length < len ? length : len - 2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting MaximumAccessibleValue - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting MaximumAccessibleValue - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting MaximumAccessibleValue", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting MaximumAccessibleValue - call to CallVoidMethod()", FALSE); @@ -4544,9 +4512,7 @@ AccessBridgeJavaEntryPoints::getMinimumAccessibleValueFromContext(jobject access wcsncpy(value, stringBytes, len); length = jniEnv->GetStringLength(js); value[length < len ? length : len - 2] = (wchar_t) 0; - EXCEPTION_CHECK("Getting MinimumAccessibleValue - call to GetStringLength()", FALSE); - jniEnv->ReleaseStringChars(js, stringBytes); - EXCEPTION_CHECK("Getting MinimumAccessibleValue - call to ReleaseStringChars()", FALSE); + EXCEPTION_CHECK_WITH_RELEASE("Getting MinimumAccessibleValue", FALSE, js, stringBytes); jniEnv->CallVoidMethod(accessBridgeObject, decrementReferenceMethod, js); EXCEPTION_CHECK("Getting MinimumAccessibleValue - call to CallVoidMethod()", FALSE); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java index 7f8d4a3a390..3dad5e329f6 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -468,12 +468,25 @@ private void initialize() throws PKCS11Exception { if (session == null) { session = token.getOpSession(); } - if (encrypt) { - token.p11.C_EncryptInit(session.id(), mechWithParams, - p11KeyID); + + if (type == Transformation.AES_GCM) { + // JDK-8255409 allows using useNormativeMechFirst dependent on token.p11.getVersion(); + boolean useNormativeMechFirst = false; + if (encrypt) { + token.p11.C_GCMEncryptInitWithRetry(session.id(), mechWithParams, + p11KeyID, useNormativeMechFirst); + } else { + token.p11.C_GCMDecryptInitWithRetry(session.id(), mechWithParams, + p11KeyID, useNormativeMechFirst); + } } else { - token.p11.C_DecryptInit(session.id(), mechWithParams, - p11KeyID); + if (encrypt) { + token.p11.C_EncryptInit(session.id(), mechWithParams, + p11KeyID); + } else { + token.p11.C_DecryptInit(session.id(), mechWithParams, + p11KeyID); + } } } catch (PKCS11Exception e) { p11Key.releaseKeyID(); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PBE_PARAMS.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PBE_PARAMS.java index e8b048869c4..7b874ced493 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PBE_PARAMS.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/CK_PBE_PARAMS.java @@ -121,11 +121,6 @@ public String toString() { sb.append(pPassword.length); sb.append(Constants.NEWLINE); - sb.append(Constants.INDENT); - sb.append("pPassword: "); - sb.append(pPassword); - sb.append(Constants.NEWLINE); - sb.append(Constants.INDENT); sb.append("ulSaltLen: "); sb.append(pSalt.length); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java index 04a369f453c..93224dd55bb 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/wrapper/PKCS11.java @@ -728,6 +728,24 @@ public native long[] C_FindObjects(long hSession, long ulMaxObjectCount) public native void C_EncryptInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception; + /** + * C_GCMEncryptInitWithRetry initializes a GCM encryption operation and retry + * with alternative param structure for max compatibility. + * (Encryption and decryption) + * + * @param hSession the session's handle + * (PKCS#11 param: CK_SESSION_HANDLE hSession) + * @param pMechanism the encryption mechanism + * (PKCS#11 param: CK_MECHANISM_PTR pMechanism) + * @param hKey the handle of the encryption key + * (PKCS#11 param: CK_OBJECT_HANDLE hKey) + * @param useNormativeVerFirst whether to use normative version of GCM parameter first + * @exception PKCS11Exception If function returns other value than CKR_OK. + * @preconditions + * @postconditions + */ + public native void C_GCMEncryptInitWithRetry(long hSession, CK_MECHANISM pMechanism, + long hKey, boolean useNormativeVerFirst) throws PKCS11Exception; /** * C_Encrypt encrypts single-part data. @@ -823,6 +841,24 @@ public native int C_EncryptFinal(long hSession, long directOut, byte[] out, public native void C_DecryptInit(long hSession, CK_MECHANISM pMechanism, long hKey) throws PKCS11Exception; + /** + * C_GCMDecryptInitWithRetry initializes a GCM decryption operation + * with alternative param structure for max compatibility. + * (Encryption and decryption) + * + * @param hSession the session's handle + * (PKCS#11 param: CK_SESSION_HANDLE hSession) + * @param pMechanism the decryption mechanism + * (PKCS#11 param: CK_MECHANISM_PTR pMechanism) + * @param hKey the handle of the decryption key + * (PKCS#11 param: CK_OBJECT_HANDLE hKey) + * @param useNormativeVerFirst whether to use normative version of GCM parameter first + * @exception PKCS11Exception If function returns other value than CKR_OK. + * @preconditions + * @postconditions + */ + public native void C_GCMDecryptInitWithRetry(long hSession, CK_MECHANISM pMechanism, + long hKey, boolean useNormativeVerFirst) throws PKCS11Exception; /** * C_Decrypt decrypts encrypted data in a single part. diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c index d941b574cc7..3ea91a6cfd1 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_convert.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -1014,18 +1014,19 @@ jAesCtrParamsToCKAesCtrParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength) } /* - * converts the Java CK_GCM_PARAMS object to a CK_GCM_PARAMS_NO_IVBITS pointer - * Note: Need to try NSS definition first to avoid SIGSEGV. + * converts the Java CK_GCM_PARAMS object to a CK_GCM_PARAMS pointer + * Note: Early NSS versions crash w/ CK_GCM_PARAMS and need to use + * CK_GCM_PARAMS_NO_IVBITS to avoid SIGSEGV. * * @param env - used to call JNI funktions to get the Java classes and objects * @param jParam - the Java CK_GCM_PARAMS object to convert * @param pLength - length of the allocated memory of the returned pointer - * @return pointer to the new CK_GCM_PARAMS_NO_IVBITS structure + * @return pointer to the new CK_GCM_PARAMS structure */ -CK_GCM_PARAMS_NO_IVBITS_PTR +CK_GCM_PARAMS_PTR jGCMParamsToCKGCMParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength) { - CK_GCM_PARAMS_NO_IVBITS_PTR ckParamPtr; + CK_GCM_PARAMS_PTR ckParamPtr; jclass jGcmParamsClass; jfieldID fieldID; jobject jIv, jAad; @@ -1053,8 +1054,8 @@ jGCMParamsToCKGCMParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength) if (fieldID == NULL) { return NULL; } jTagLen = (*env)->GetLongField(env, jParam, fieldID); - // allocate memory for CK_GCM_PARAMS_NO_IVBITS pointer - ckParamPtr = calloc(1, sizeof(CK_GCM_PARAMS_NO_IVBITS)); + // allocate memory for CK_GCM_PARAMS pointer + ckParamPtr = calloc(1, sizeof(CK_GCM_PARAMS)); if (ckParamPtr == NULL) { throwOutOfMemoryError(env, 0); return NULL; @@ -1065,6 +1066,8 @@ jGCMParamsToCKGCMParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength) if ((*env)->ExceptionCheck(env)) { goto cleanup; } + // adjust since the value is in bits + ckParamPtr->ulIvBits = ckParamPtr->ulIvLen << 3; jByteArrayToCKByteArray(env, jAad, &(ckParamPtr->pAAD), &(ckParamPtr->ulAADLen)); if ((*env)->ExceptionCheck(env)) { @@ -1074,9 +1077,9 @@ jGCMParamsToCKGCMParamPtr(JNIEnv *env, jobject jParam, CK_ULONG *pLength) ckParamPtr->ulTagBits = jLongToCKULong(jTagLen); if (pLength != NULL) { - *pLength = sizeof(CK_GCM_PARAMS_NO_IVBITS); + *pLength = sizeof(CK_GCM_PARAMS); } - TRACE1("Created inner GCM_PARAMS PTR w/o ulIvBits %p\n", ckParamPtr); + TRACE1("Created inner GCM_PARAMS PTR %p\n", ckParamPtr); return ckParamPtr; cleanup: free(ckParamPtr->pIv); diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c index 1a94d3c4dc7..da65a453df8 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_crypt.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -72,7 +72,6 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1EncryptInit { CK_SESSION_HANDLE ckSessionHandle; CK_MECHANISM_PTR ckpMechanism = NULL; - CK_MECHANISM_PTR ckpTemp; CK_OBJECT_HANDLE ckKeyHandle; CK_RV rv; @@ -90,20 +89,60 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1EncryptInit rv = (*ckpFunctions->C_EncryptInit)(ckSessionHandle, ckpMechanism, ckKeyHandle); - if (ckpMechanism->mechanism == CKM_AES_GCM) { - if (rv == CKR_ARGUMENTS_BAD || rv == CKR_MECHANISM_PARAM_INVALID) { - // retry with CKM_GCM_PARAMS structure in pkcs11t.h - TRACE0("DEBUG C_EncryptInit: retry with CK_GCM_PARAMS\n"); - ckpTemp = updateGCMParams(env, ckpMechanism); - if (ckpTemp != NULL) { // only re-call if conversion succeeds - ckpMechanism = ckpTemp; - rv = (*ckpFunctions->C_EncryptInit)(ckSessionHandle, ckpMechanism, - ckKeyHandle); - } + TRACE1("DEBUG C_EncryptInit: freed pMech = %p\n", ckpMechanism); + freeCKMechanismPtr(ckpMechanism); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } + + TRACE0("FINISHED\n"); +} + +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_GCMEncryptInitWithRetry + * Signature: (JLsun/security/pkcs11/wrapper/CK_MECHANISM;JZ)V + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + * @param jobject jMechanism CK_MECHANISM_PTR pMechanism + * @param jlong jKeyHandle CK_OBJECT_HANDLE hKey + * @param jboolean useNormVerFirst CK_BBOOL retry (only retry if the first + * init uses the non-normative version) + */ +JNIEXPORT void JNICALL +Java_sun_security_pkcs11_wrapper_PKCS11_C_1GCMEncryptInitWithRetry +(JNIEnv *env, jobject obj, jlong jSessionHandle, + jobject jMechanism, jlong jKeyHandle, jboolean useNormVerFirst) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_MECHANISM_PTR ckpMechanism = NULL; + CK_OBJECT_HANDLE ckKeyHandle; + CK_BBOOL retry = FALSE; + CK_RV rv = 1; + + CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); + if (ckpFunctions == NULL) { return; } + + ckSessionHandle = jLongToCKULong(jSessionHandle); + ckKeyHandle = jLongToCKULong(jKeyHandle); + ckpMechanism = jMechanismToCKMechanismPtr(env, jMechanism); + + if ((*env)->ExceptionCheck(env)) { return; } + + // if !useNormVerFirst, then update 'ckpMechanism' in place w/ + // non-normative GCM params. + retry = (!useNormVerFirst && updateGCMParams(env, ckpMechanism) != NULL); + + rv = (*ckpFunctions->C_EncryptInit)(ckSessionHandle, ckpMechanism, ckKeyHandle); + + if (rv == CKR_ARGUMENTS_BAD || rv == CKR_MECHANISM_PARAM_INVALID) { + // retry and update 'ckpMechanism' in place w/ normative GCM params. + if (retry && updateGCMParams(env, ckpMechanism) != NULL) { + TRACE0("DEBUG retry C_EncryptInit\n"); + rv = (*ckpFunctions->C_EncryptInit)(ckSessionHandle, + ckpMechanism, ckKeyHandle); } } - TRACE1("DEBUG C_EncryptInit: freed pMech = %p\n", ckpMechanism); + TRACE1("DEBUG C_GCMEncryptInitWithRetry: freed pMech = %p\n", ckpMechanism); freeCKMechanismPtr(ckpMechanism); if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } @@ -310,7 +349,6 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1DecryptInit { CK_SESSION_HANDLE ckSessionHandle; CK_MECHANISM_PTR ckpMechanism = NULL; - CK_MECHANISM_PTR ckpTemp; CK_OBJECT_HANDLE ckKeyHandle; CK_RV rv; @@ -328,20 +366,61 @@ Java_sun_security_pkcs11_wrapper_PKCS11_C_1DecryptInit rv = (*ckpFunctions->C_DecryptInit)(ckSessionHandle, ckpMechanism, ckKeyHandle); - if (ckpMechanism->mechanism == CKM_AES_GCM) { - if (rv == CKR_ARGUMENTS_BAD || rv == CKR_MECHANISM_PARAM_INVALID) { - // retry with CKM_GCM_PARAMS structure in pkcs11t.h - TRACE0("DEBUG C_DecryptInit: retry with CK_GCM_PARAMS\n"); - ckpTemp = updateGCMParams(env, ckpMechanism); - if (ckpTemp != NULL) { // only re-call if conversion succeeds - ckpMechanism = ckpTemp; - rv = (*ckpFunctions->C_DecryptInit)(ckSessionHandle, ckpMechanism, - ckKeyHandle); - } + TRACE1("DEBUG C_DecryptInit: freed pMech = %p\n", ckpMechanism); + freeCKMechanismPtr(ckpMechanism); + if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } + + TRACE0("FINISHED\n"); +} + +/* + * Class: sun_security_pkcs11_wrapper_PKCS11 + * Method: C_GCMDecryptInitWithRetry + * Signature: (JLsun/security/pkcs11/wrapper/CK_MECHANISM;JZ)V + * Parametermapping: *PKCS11* + * @param jlong jSessionHandle CK_SESSION_HANDLE hSession + * @param jobject jMechanism CK_MECHANISM_PTR pMechanism + * @param jlong jKeyHandle CK_OBJECT_HANDLE hKey + * @param jboolean useNormVerFirst CK_BBOOL retry (only retry if the first + * init uses the non-normative version) + */ +JNIEXPORT void JNICALL +Java_sun_security_pkcs11_wrapper_PKCS11_C_1GCMDecryptInitWithRetry +(JNIEnv *env, jobject obj, jlong jSessionHandle, + jobject jMechanism, jlong jKeyHandle, jboolean useNormVerFirst) +{ + CK_SESSION_HANDLE ckSessionHandle; + CK_MECHANISM_PTR ckpMechanism = NULL; + CK_OBJECT_HANDLE ckKeyHandle; + CK_BBOOL retry = FALSE; + CK_RV rv = 1; + + CK_FUNCTION_LIST_PTR ckpFunctions = getFunctionList(env, obj); + if (ckpFunctions == NULL) { return; } + + ckSessionHandle = jLongToCKULong(jSessionHandle); + ckKeyHandle = jLongToCKULong(jKeyHandle); + ckpMechanism = jMechanismToCKMechanismPtr(env, jMechanism); + + if ((*env)->ExceptionCheck(env)) { return; } + + // if !useNormVerFirst, then update 'ckpMechanism' in place w/ + // non-normative GCM params. + retry = (!useNormVerFirst && updateGCMParams(env, ckpMechanism) != NULL); + + rv = (*ckpFunctions->C_DecryptInit)(ckSessionHandle, ckpMechanism, + ckKeyHandle); + + if (rv == CKR_ARGUMENTS_BAD || rv == CKR_MECHANISM_PARAM_INVALID) { + // retry and update 'ckpMechanism' in place w/ normative GCM params. + if (retry && updateGCMParams(env, ckpMechanism) != NULL) { + TRACE0("DEBUG retry C_DecryptInit with normative CK_GCM_PARAMS\n"); + rv = (*ckpFunctions->C_DecryptInit)(ckSessionHandle, ckpMechanism, + ckKeyHandle); } } - TRACE1("DEBUG C_DecryptInit: freed pMech = %p\n", ckpMechanism); + TRACE1("DEBUG C_GCMDecryptInitWithRetry: freed pMech = %p\n", ckpMechanism); freeCKMechanismPtr(ckpMechanism); if (ckAssertReturnValueOK(env, rv) != CK_ASSERT_OK) { return; } diff --git a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c index 27006b9da0e..192d8ae8d72 100644 --- a/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c +++ b/src/jdk.crypto.cryptoki/share/native/libj2pkcs11/p11_util.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. */ /* Copyright (c) 2002 Graz University of Technology. All rights reserved. @@ -308,14 +308,14 @@ void freeCKMechanismPtr(CK_MECHANISM_PTR mechPtr) { tmp = mechPtr->pParameter; switch (mechPtr->mechanism) { case CKM_AES_GCM: - if (mechPtr->ulParameterLen == sizeof(CK_GCM_PARAMS_NO_IVBITS)) { - TRACE0("[ GCM_PARAMS w/o ulIvBits ]\n"); - free(((CK_GCM_PARAMS_NO_IVBITS*)tmp)->pIv); - free(((CK_GCM_PARAMS_NO_IVBITS*)tmp)->pAAD); - } else if (mechPtr->ulParameterLen == sizeof(CK_GCM_PARAMS)) { + if (mechPtr->ulParameterLen == sizeof(CK_GCM_PARAMS)) { TRACE0("[ GCM_PARAMS ]\n"); free(((CK_GCM_PARAMS*)tmp)->pIv); free(((CK_GCM_PARAMS*)tmp)->pAAD); + } else if (mechPtr->ulParameterLen == sizeof(CK_GCM_PARAMS_NO_IVBITS)) { + TRACE0("[ GCM_PARAMS w/o ulIvBits ]\n"); + free(((CK_GCM_PARAMS_NO_IVBITS*)tmp)->pIv); + free(((CK_GCM_PARAMS_NO_IVBITS*)tmp)->pAAD); } break; case CKM_AES_CCM: @@ -411,43 +411,54 @@ void freeCKMechanismPtr(CK_MECHANISM_PTR mechPtr) { } } -/* This function replaces the CK_GCM_PARAMS_NO_IVBITS structure associated - * with the specified CK_MECHANISM structure with CK_GCM_PARAMS - * structure. +/* This function updates the specified CK_MECHANISM structure + * and its GCM parameter structure switching between CK_GCM_PARAMS and + * CK_GCM_PARAMS_NO_IVBITS. * * @param mechPtr pointer to the CK_MECHANISM structure containing - * the to-be-converted CK_GCM_PARAMS_NO_IVBITS structure. + * the to-be-converted CK_GCM_PARAMS / CK_GCM_PARAMS_NO_IVBITS structure. * @return pointer to the CK_MECHANISM structure containing the - * converted CK_GCM_PARAMS structure or NULL if no conversion took place. + * converted structure or NULL if no conversion is done. */ CK_MECHANISM_PTR updateGCMParams(JNIEnv *env, CK_MECHANISM_PTR mechPtr) { - CK_GCM_PARAMS* pGcmParams2 = NULL; - CK_GCM_PARAMS_NO_IVBITS* pParams = NULL; - if ((mechPtr->mechanism == CKM_AES_GCM) && - (mechPtr->pParameter != NULL_PTR) && - (mechPtr->ulParameterLen == sizeof(CK_GCM_PARAMS_NO_IVBITS))) { - pGcmParams2 = calloc(1, sizeof(CK_GCM_PARAMS)); - if (pGcmParams2 == NULL) { - throwOutOfMemoryError(env, 0); - return NULL; + CK_GCM_PARAMS_PTR pParams; + CK_GCM_PARAMS_NO_IVBITS_PTR pParamsNoIvBits; + CK_ULONG paramLen; + + if (mechPtr != NULL) { + paramLen = mechPtr->ulParameterLen; + if (paramLen == sizeof(CK_GCM_PARAMS)) { + // CK_GCM_PARAMS => CK_GCM_PARAMS_NO_IVBITS + pParams = (CK_GCM_PARAMS*) mechPtr->pParameter; + pParamsNoIvBits = calloc(1, sizeof(CK_GCM_PARAMS_NO_IVBITS)); + pParamsNoIvBits->pIv = pParams->pIv; + pParamsNoIvBits->ulIvLen = pParams->ulIvLen; + pParamsNoIvBits->pAAD = pParams->pAAD; + pParamsNoIvBits->ulAADLen = pParams->ulAADLen; + pParamsNoIvBits->ulTagBits = pParams->ulTagBits; + mechPtr->pParameter = pParamsNoIvBits; + mechPtr->ulParameterLen = sizeof(CK_GCM_PARAMS_NO_IVBITS); + free(pParams); + TRACE0("DEBUG update CK_GCM_PARAMS to CK_GCM_PARAMS_NO_IVBITS\n"); + return mechPtr; + } else if (paramLen == sizeof(CK_GCM_PARAMS_NO_IVBITS)) { + // CK_GCM_PARAMS_NO_IVBITS => CK_GCM_PARAMS + pParamsNoIvBits = (CK_GCM_PARAMS_NO_IVBITS*) mechPtr->pParameter; + pParams = calloc(1, sizeof(CK_GCM_PARAMS)); + pParams->pIv = pParamsNoIvBits->pIv; + pParams->ulIvLen = pParamsNoIvBits->ulIvLen; + pParams->ulIvBits = pParamsNoIvBits->ulIvLen << 3; + pParams->pAAD = pParamsNoIvBits->pAAD; + pParams->ulAADLen = pParamsNoIvBits->ulAADLen; + pParams->ulTagBits = pParamsNoIvBits->ulTagBits; + mechPtr->pParameter = pParams; + mechPtr->ulParameterLen = sizeof(CK_GCM_PARAMS); + free(pParamsNoIvBits); + TRACE0("DEBUG update CK_GCM_PARAMS_NO_IVBITS to CK_GCM_PARAMS\n"); + return mechPtr; } - pParams = (CK_GCM_PARAMS_NO_IVBITS*) mechPtr->pParameter; - pGcmParams2->pIv = pParams->pIv; - pGcmParams2->ulIvLen = pParams->ulIvLen; - pGcmParams2->ulIvBits = (pGcmParams2->ulIvLen << 3); - pGcmParams2->pAAD = pParams->pAAD; - pGcmParams2->ulAADLen = pParams->ulAADLen; - pGcmParams2->ulTagBits = pParams->ulTagBits; - TRACE1("DEBUG updateGCMParams: pMech %p\n", mechPtr); - TRACE2("\t=> GCM param w/o ulIvBits %p => GCM param %p\n", pParams, - pGcmParams2); - free(pParams); - mechPtr->pParameter = pGcmParams2; - mechPtr->ulParameterLen = sizeof(CK_GCM_PARAMS); - return mechPtr; - } else { - TRACE0("DEBUG updateGCMParams: no conversion done\n"); } + TRACE0("DEBUG updateGCMParams: no conversion done\n"); return NULL; } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java index 03e2a9ee8f5..0e136d80437 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -42,8 +42,10 @@ class Request { private SocketChannel chan; private InputStream is; private OutputStream os; + private final int maxReqHeaderSize; Request (InputStream rawInputStream, OutputStream rawout) throws IOException { + this.maxReqHeaderSize = ServerConfig.getMaxReqHeaderSize(); is = rawInputStream; os = rawout; do { @@ -76,6 +78,7 @@ public OutputStream outputStream () { public String readLine () throws IOException { boolean gotCR = false, gotLF = false; pos = 0; lineBuf = new StringBuffer(); + long lsize = 32; while (!gotLF) { int c = is.read(); if (c == -1) { @@ -88,20 +91,27 @@ public String readLine () throws IOException { gotCR = false; consume (CR); consume (c); + lsize = lsize + 2; } } else { if (c == CR) { gotCR = true; } else { consume (c); + lsize = lsize + 1; } } + if (maxReqHeaderSize > 0 && lsize > maxReqHeaderSize) { + throw new IOException("Maximum header (" + + "sun.net.httpserver.maxReqHeaderSize) exceeded, " + + ServerConfig.getMaxReqHeaderSize() + "."); + } } lineBuf.append (buf, 0, pos); return new String (lineBuf); } - private void consume (int c) { + private void consume (int c) throws IOException { if (pos == BUF_LEN) { lineBuf.append (buf); pos = 0; @@ -139,13 +149,22 @@ Headers headers () throws IOException { len = 1; firstc = c; } + long hsize = startLine.length() + 32L; while (firstc != LF && firstc != CR && firstc >= 0) { int keyend = -1; int c; boolean inKey = firstc > ' '; s[len++] = (char) firstc; + hsize = hsize + 1; parseloop:{ + // We start parsing for a new name value pair here. + // The max header size includes an overhead of 32 bytes per + // name value pair. + // See SETTINGS_MAX_HEADER_LIST_SIZE, RFC 9113, section 6.5.2. + long maxRemaining = maxReqHeaderSize > 0 + ? maxReqHeaderSize - hsize - 32 + : Long.MAX_VALUE; while ((c = is.read()) >= 0) { switch (c) { /*fallthrough*/ @@ -179,6 +198,11 @@ Headers headers () throws IOException { s = ns; } s[len++] = (char) c; + if (maxReqHeaderSize > 0 && len > maxRemaining) { + throw new IOException("Maximum header (" + + "sun.net.httpserver.maxReqHeaderSize) exceeded, " + + ServerConfig.getMaxReqHeaderSize() + "."); + } } firstc = -1; } @@ -206,6 +230,13 @@ Headers headers () throws IOException { "sun.net.httpserver.maxReqHeaders) exceeded, " + ServerConfig.getMaxReqHeaders() + "."); } + hsize = hsize + len + 32; + if (maxReqHeaderSize > 0 && hsize > maxReqHeaderSize) { + throw new IOException("Maximum header (" + + "sun.net.httpserver.maxReqHeaderSize) exceeded, " + + ServerConfig.getMaxReqHeaderSize() + "."); + } + if (k == null) { // Headers disallows null keys, use empty string k = ""; // instead to represent invalid key } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerConfig.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerConfig.java index 34a50fcab3f..de2916bf468 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerConfig.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2024, 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 @@ -48,6 +48,7 @@ class ServerConfig { // timing out request/response if max request/response time is configured private static final long DEFAULT_REQ_RSP_TIMER_TASK_SCHEDULE_MILLIS = 1000; private static final int DEFAULT_MAX_REQ_HEADERS = 200; + private static final int DEFAULT_MAX_REQ_HEADER_SIZE = 380 * 1024; private static final long DEFAULT_DRAIN_AMOUNT = 64 * 1024; private static long idleTimerScheduleMillis; @@ -61,6 +62,9 @@ class ServerConfig { private static int maxIdleConnections; // The maximum number of request headers allowable private static int maxReqHeaders; + // a maximum value for the header list size. This is the + // names size + values size + 32 bytes per field line + private static int maxReqHeadersSize; // max time a request or response is allowed to take private static long maxReqTime; private static long maxRspTime; @@ -103,6 +107,14 @@ public Void run () { "sun.net.httpserver.maxReqHeaders", DEFAULT_MAX_REQ_HEADERS); + // a value <= 0 means unlimited + maxReqHeadersSize = Integer.getInteger( + "sun.net.httpserver.maxReqHeaderSize", + DEFAULT_MAX_REQ_HEADER_SIZE); + if (maxReqHeadersSize <= 0) { + maxReqHeadersSize = 0; + } + maxReqTime = Long.getLong("sun.net.httpserver.maxReqTime", DEFAULT_MAX_REQ_TIME); @@ -211,6 +223,10 @@ static int getMaxReqHeaders() { return maxReqHeaders; } + static int getMaxReqHeaderSize() { + return maxReqHeadersSize; + } + /** * @return Returns the maximum amount of time the server will wait for the request to be read * completely. This method can return a value of 0 or negative to imply no maximum limit has diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java index 1b84ab2e681..ff6d9e47f16 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java @@ -54,10 +54,10 @@ import java.nio.channels.SocketChannel; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; -import java.util.LinkedList; import java.util.List; import java.util.Set; import java.util.Timer; @@ -161,7 +161,7 @@ class ServerImpl { logger.log (Level.DEBUG, "MAX_REQ_TIME: "+MAX_REQ_TIME); logger.log (Level.DEBUG, "MAX_RSP_TIME: "+MAX_RSP_TIME); } - events = new LinkedList(); + events = new ArrayList<>(); logger.log (Level.DEBUG, "HttpServer created "+protocol+" "+ addr); } @@ -427,8 +427,7 @@ private void handleEvent (Event r) { } } - final LinkedList connsToRegister = - new LinkedList(); + final ArrayList connsToRegister = new ArrayList<>(); void reRegister (HttpConnection c) { /* re-register with selector */ @@ -453,7 +452,7 @@ public void run() { synchronized (lolock) { if (events.size() > 0) { list = events; - events = new LinkedList(); + events = new ArrayList<>(); } } @@ -516,14 +515,15 @@ public void run() { key.cancel(); chan.configureBlocking (true); + // check if connection is being closed if (newlyAcceptedConnections.remove(conn) || idleConnections.remove(conn)) { // was either a newly accepted connection or an idle // connection. In either case, we mark that the request // has now started on this connection. requestStarted(conn); + handle (chan, conn); } - handle (chan, conn); } else { assert false : "Unexpected non-readable key:" + key; } @@ -982,35 +982,30 @@ void responseCompleted (HttpConnection c) { */ class IdleTimeoutTask extends TimerTask { public void run () { - LinkedList toClose = new LinkedList(); - final long currentTime = System.currentTimeMillis(); - synchronized (idleConnections) { - final Iterator it = idleConnections.iterator(); - while (it.hasNext()) { - final HttpConnection c = it.next(); - if (currentTime - c.idleStartTime >= IDLE_INTERVAL) { - toClose.add(c); - it.remove(); - } - } - } + closeConnections(idleConnections, IDLE_INTERVAL); // if any newly accepted connection has been idle (i.e. no byte has been sent on that // connection during the configured idle timeout period) then close it as well - synchronized (newlyAcceptedConnections) { - final Iterator it = newlyAcceptedConnections.iterator(); - while (it.hasNext()) { - final HttpConnection c = it.next(); - if (currentTime - c.idleStartTime >= NEWLY_ACCEPTED_CONN_IDLE_INTERVAL) { - toClose.add(c); - it.remove(); - } + closeConnections(newlyAcceptedConnections, NEWLY_ACCEPTED_CONN_IDLE_INTERVAL); + } + + private void closeConnections(Set connections, long idleInterval) { + long currentTime = System.currentTimeMillis(); + ArrayList toClose = new ArrayList<>(); + + connections.forEach(c -> { + if (currentTime - c.idleStartTime >= idleInterval) { + toClose.add(c); } - } + }); for (HttpConnection c : toClose) { - allConnections.remove(c); - c.close(); - if (logger.isLoggable(Level.TRACE)) { - logger.log(Level.TRACE, "Closed idle connection " + c); + // check if connection still idle + if (currentTime - c.idleStartTime >= idleInterval && + connections.remove(c)) { + allConnections.remove(c); + c.close(); + if (logger.isLoggable(Level.TRACE)) { + logger.log(Level.TRACE, "Closed idle connection " + c); + } } } } @@ -1023,7 +1018,7 @@ class ReqRspTimeoutTask extends TimerTask { // runs every TIMER_MILLIS public void run () { - LinkedList toClose = new LinkedList(); + ArrayList toClose = new ArrayList<>(); final long currentTime = System.currentTimeMillis(); synchronized (reqConnections) { if (MAX_REQ_TIME != -1) { @@ -1040,7 +1035,7 @@ public void run () { } } } - toClose = new LinkedList(); + toClose = new ArrayList<>(); synchronized (rspConnections) { if (MAX_RSP_TIME != -1) { for (HttpConnection c : rspConnections) { diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java index d41443f22ec..fd2fc1dc4ce 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/HtmlDoclet.java @@ -220,7 +220,7 @@ protected void generateOtherFiles(DocletEnvironment docEnv, ClassTree classtree) private void copyJqueryFiles() throws DocletException { List files = Arrays.asList( - "jquery-3.6.1.min.js", + "jquery-3.7.1.min.js", "jquery-ui.min.js", "jquery-ui.min.css", "external/jquery/jquery.js", diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-3.6.1.min.js b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-3.6.1.min.js deleted file mode 100644 index 2c69bc908b1..00000000000 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-3.6.1.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="

    ",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 0 && ( length - 1 ) in obj; } -var Sizzle = -/*! - * Sizzle CSS Selector Engine v2.3.6 - * https://sizzlejs.com/ - * - * Copyright JS Foundation and other contributors - * Released under the MIT license - * https://js.foundation/ - * - * Date: 2021-02-16 - */ -( function( window ) { + + +function nodeName( elem, name ) { + + return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); + +} +var pop = arr.pop; + + +var sort = arr.sort; + + +var splice = arr.splice; + + +var whitespace = "[\\x20\\t\\r\\n\\f]"; + + +var rtrimCSS = new RegExp( + "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", + "g" +); + + + + +// Note: an element does not contain itself +jQuery.contains = function( a, b ) { + var bup = b && b.parentNode; + + return a === bup || !!( bup && bup.nodeType === 1 && ( + + // Support: IE 9 - 11+ + // IE doesn't have `contains` on SVG. + a.contains ? + a.contains( bup ) : + a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 + ) ); +}; + + + + +// CSS string/identifier serialization +// https://drafts.csswg.org/cssom/#common-serializing-idioms +var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g; + +function fcssescape( ch, asCodePoint ) { + if ( asCodePoint ) { + + // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER + if ( ch === "\0" ) { + return "\uFFFD"; + } + + // Control characters and (dependent upon position) numbers get escaped as code points + return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + } + + // Other potentially-special ASCII characters get backslash-escaped + return "\\" + ch; +} + +jQuery.escapeSelector = function( sel ) { + return ( sel + "" ).replace( rcssescape, fcssescape ); +}; + + + + +var preferredDoc = document, + pushNative = push; + +( function() { + var i, - support, Expr, - getText, - isXML, - tokenize, - compile, - select, outermostContext, sortInput, hasDuplicate, + push = pushNative, // Local document vars - setDocument, document, - docElem, + documentElement, documentIsHTML, rbuggyQSA, - rbuggyMatches, matches, - contains, // Instance-specific data - expando = "sizzle" + 1 * new Date(), - preferredDoc = window.document, + expando = jQuery.expando, dirruns = 0, done = 0, classCache = createCache(), @@ -570,47 +664,22 @@ var i, return 0; }, - // Instance methods - hasOwn = ( {} ).hasOwnProperty, - arr = [], - pop = arr.pop, - pushNative = arr.push, - push = arr.push, - slice = arr.slice, - - // Use a stripped-down indexOf as it's faster than native - // https://jsperf.com/thor-indexof-vs-for/5 - indexOf = function( list, elem ) { - var i = 0, - len = list.length; - for ( ; i < len; i++ ) { - if ( list[ i ] === elem ) { - return i; - } - } - return -1; - }, - - booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|" + - "ismap|loop|multiple|open|readonly|required|scoped", + booleans = "checked|selected|async|autofocus|autoplay|controls|defer|disabled|hidden|ismap|" + + "loop|multiple|open|readonly|required|scoped", // Regular expressions - // http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // https://www.w3.org/TR/css-syntax-3/#ident-token-diagram identifier = "(?:\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\[^\\r\\n\\f]|[\\w-]|[^\0-\\x7f])+", - // Attribute selectors: http://www.w3.org/TR/selectors/#attribute-selectors + // Attribute selectors: https://www.w3.org/TR/selectors/#attribute-selectors attributes = "\\[" + whitespace + "*(" + identifier + ")(?:" + whitespace + // Operator (capture 2) "*([*^$|!~]?=)" + whitespace + - // "Attribute values must be CSS identifiers [capture 5] - // or strings [capture 3 or capture 4]" + // "Attribute values must be CSS identifiers [capture 5] or strings [capture 3 or capture 4]" "*(?:'((?:\\\\.|[^\\\\'])*)'|\"((?:\\\\.|[^\\\\\"])*)\"|(" + identifier + "))|)" + whitespace + "*\\]", @@ -629,101 +698,88 @@ var i, // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter rwhitespace = new RegExp( whitespace + "+", "g" ), - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + - whitespace + "+$", "g" ), rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + whitespace + - "*" ), + rleadingCombinator = new RegExp( "^" + whitespace + "*([>+~]|" + whitespace + ")" + + whitespace + "*" ), rdescend = new RegExp( whitespace + "|>" ), rpseudo = new RegExp( pseudos ), ridentifier = new RegExp( "^" + identifier + "$" ), matchExpr = { - "ID": new RegExp( "^#(" + identifier + ")" ), - "CLASS": new RegExp( "^\\.(" + identifier + ")" ), - "TAG": new RegExp( "^(" + identifier + "|[*])" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "CHILD": new RegExp( "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + - whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + - whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - "bool": new RegExp( "^(?:" + booleans + ")$", "i" ), + ID: new RegExp( "^#(" + identifier + ")" ), + CLASS: new RegExp( "^\\.(" + identifier + ")" ), + TAG: new RegExp( "^(" + identifier + "|[*])" ), + ATTR: new RegExp( "^" + attributes ), + PSEUDO: new RegExp( "^" + pseudos ), + CHILD: new RegExp( + "^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\(" + + whitespace + "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + + whitespace + "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), + bool: new RegExp( "^(?:" + booleans + ")$", "i" ), // For use in libraries implementing .is() // We use this for POS matching in `select` - "needsContext": new RegExp( "^" + whitespace + + needsContext: new RegExp( "^" + whitespace + "*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", "i" ) }, - rhtml = /HTML$/i, rinputs = /^(?:input|select|textarea|button)$/i, rheader = /^h\d$/i, - rnative = /^[^{]+\{\s*\[native \w/, - // Easily-parseable/retrievable ID or TAG or CLASS selectors rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/, rsibling = /[+~]/, // CSS escapes - // http://www.w3.org/TR/CSS21/syndata.html#escaped-characters - runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + "?|\\\\([^\\r\\n\\f])", "g" ), + // https://www.w3.org/TR/CSS21/syndata.html#escaped-characters + runescape = new RegExp( "\\\\[\\da-fA-F]{1,6}" + whitespace + + "?|\\\\([^\\r\\n\\f])", "g" ), funescape = function( escape, nonHex ) { var high = "0x" + escape.slice( 1 ) - 0x10000; - return nonHex ? + if ( nonHex ) { // Strip the backslash prefix from a non-hex escape sequence - nonHex : - - // Replace a hexadecimal escape sequence with the encoded Unicode code point - // Support: IE <=11+ - // For values outside the Basic Multilingual Plane (BMP), manually construct a - // surrogate pair - high < 0 ? - String.fromCharCode( high + 0x10000 ) : - String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); - }, - - // CSS string/identifier serialization - // https://drafts.csswg.org/cssom/#common-serializing-idioms - rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g, - fcssescape = function( ch, asCodePoint ) { - if ( asCodePoint ) { - - // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER - if ( ch === "\0" ) { - return "\uFFFD"; - } - - // Control characters and (dependent upon position) numbers get escaped as code points - return ch.slice( 0, -1 ) + "\\" + - ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " "; + return nonHex; } - // Other potentially-special ASCII characters get backslash-escaped - return "\\" + ch; + // Replace a hexadecimal escape sequence with the encoded Unicode code point + // Support: IE <=11+ + // For values outside the Basic Multilingual Plane (BMP), manually construct a + // surrogate pair + return high < 0 ? + String.fromCharCode( high + 0x10000 ) : + String.fromCharCode( high >> 10 | 0xD800, high & 0x3FF | 0xDC00 ); }, - // Used for iframes - // See setDocument() + // Used for iframes; see `setDocument`. + // Support: IE 9 - 11+, Edge 12 - 18+ // Removing the function wrapper causes a "Permission Denied" - // error in IE + // error in IE/Edge. unloadHandler = function() { setDocument(); }, inDisabledFieldset = addCombinator( function( elem ) { - return elem.disabled === true && elem.nodeName.toLowerCase() === "fieldset"; + return elem.disabled === true && nodeName( elem, "fieldset" ); }, { dir: "parentNode", next: "legend" } ); +// Support: IE <=9 only +// Accessing document.activeElement can throw unexpectedly +// https://bugs.jquery.com/ticket/13393 +function safeActiveElement() { + try { + return document.activeElement; + } catch ( err ) { } +} + // Optimize for push.apply( _, NodeList ) try { push.apply( @@ -731,32 +787,22 @@ try { preferredDoc.childNodes ); - // Support: Android<4.0 + // Support: Android <=4.0 // Detect silently failing push.apply // eslint-disable-next-line no-unused-expressions arr[ preferredDoc.childNodes.length ].nodeType; } catch ( e ) { - push = { apply: arr.length ? - - // Leverage slice if possible - function( target, els ) { + push = { + apply: function( target, els ) { pushNative.apply( target, slice.call( els ) ); - } : - - // Support: IE<9 - // Otherwise append directly - function( target, els ) { - var j = target.length, - i = 0; - - // Can't trust NodeList.length - while ( ( target[ j++ ] = els[ i++ ] ) ) {} - target.length = j - 1; + }, + call: function( target ) { + pushNative.apply( target, slice.call( arguments, 1 ) ); } }; } -function Sizzle( selector, context, results, seed ) { +function find( selector, context, results, seed ) { var m, i, elem, nid, match, groups, newSelector, newContext = context && context.ownerDocument, @@ -790,11 +836,10 @@ function Sizzle( selector, context, results, seed ) { if ( nodeType === 9 ) { if ( ( elem = context.getElementById( m ) ) ) { - // Support: IE, Opera, Webkit - // TODO: identify versions + // Support: IE 9 only // getElementById can match elements by name instead of ID if ( elem.id === m ) { - results.push( elem ); + push.call( results, elem ); return results; } } else { @@ -804,14 +849,13 @@ function Sizzle( selector, context, results, seed ) { // Element context } else { - // Support: IE, Opera, Webkit - // TODO: identify versions + // Support: IE 9 only // getElementById can match elements by name instead of ID if ( newContext && ( elem = newContext.getElementById( m ) ) && - contains( context, elem ) && + find.contains( context, elem ) && elem.id === m ) { - results.push( elem ); + push.call( results, elem ); return results; } } @@ -822,22 +866,15 @@ function Sizzle( selector, context, results, seed ) { return results; // Class selector - } else if ( ( m = match[ 3 ] ) && support.getElementsByClassName && - context.getElementsByClassName ) { - + } else if ( ( m = match[ 3 ] ) && context.getElementsByClassName ) { push.apply( results, context.getElementsByClassName( m ) ); return results; } } // Take advantage of querySelectorAll - if ( support.qsa && - !nonnativeSelectorCache[ selector + " " ] && - ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) && - - // Support: IE 8 only - // Exclude object elements - ( nodeType !== 1 || context.nodeName.toLowerCase() !== "object" ) ) { + if ( !nonnativeSelectorCache[ selector + " " ] && + ( !rbuggyQSA || !rbuggyQSA.test( selector ) ) ) { newSelector = selector; newContext = context; @@ -850,7 +887,7 @@ function Sizzle( selector, context, results, seed ) { // as such selectors are not recognized by querySelectorAll. // Thanks to Andrew Dupont for this technique. if ( nodeType === 1 && - ( rdescend.test( selector ) || rcombinators.test( selector ) ) ) { + ( rdescend.test( selector ) || rleadingCombinator.test( selector ) ) ) { // Expand context for sibling selectors newContext = rsibling.test( selector ) && testContext( context.parentNode ) || @@ -858,11 +895,15 @@ function Sizzle( selector, context, results, seed ) { // We can use :scope instead of the ID hack if the browser // supports it & if we're not changing the context. - if ( newContext !== context || !support.scope ) { + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when + // strict-comparing two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + if ( newContext != context || !support.scope ) { // Capture the context ID, setting it first if necessary if ( ( nid = context.getAttribute( "id" ) ) ) { - nid = nid.replace( rcssescape, fcssescape ); + nid = jQuery.escapeSelector( nid ); } else { context.setAttribute( "id", ( nid = expando ) ); } @@ -895,7 +936,7 @@ function Sizzle( selector, context, results, seed ) { } // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed ); + return select( selector.replace( rtrimCSS, "$1" ), context, results, seed ); } /** @@ -909,7 +950,8 @@ function createCache() { function cache( key, value ) { - // Use (key + " ") to avoid collision with native prototype properties (see Issue #157) + // Use (key + " ") to avoid collision with native prototype properties + // (see https://github.com/jquery/sizzle/issues/157) if ( keys.push( key + " " ) > Expr.cacheLength ) { // Only keep the most recent entries @@ -921,7 +963,7 @@ function createCache() { } /** - * Mark a function for special use by Sizzle + * Mark a function for special use by jQuery selector module * @param {Function} fn The function to mark */ function markFunction( fn ) { @@ -952,56 +994,13 @@ function assert( fn ) { } } -/** - * Adds the same handler for all of the specified attrs - * @param {String} attrs Pipe-separated list of attributes - * @param {Function} handler The method that will be applied - */ -function addHandle( attrs, handler ) { - var arr = attrs.split( "|" ), - i = arr.length; - - while ( i-- ) { - Expr.attrHandle[ arr[ i ] ] = handler; - } -} - -/** - * Checks document order of two siblings - * @param {Element} a - * @param {Element} b - * @returns {Number} Returns less than 0 if a precedes b, greater than 0 if a follows b - */ -function siblingCheck( a, b ) { - var cur = b && a, - diff = cur && a.nodeType === 1 && b.nodeType === 1 && - a.sourceIndex - b.sourceIndex; - - // Use IE sourceIndex if available on both nodes - if ( diff ) { - return diff; - } - - // Check if b follows a - if ( cur ) { - while ( ( cur = cur.nextSibling ) ) { - if ( cur === b ) { - return -1; - } - } - } - - return a ? 1 : -1; -} - /** * Returns a function to use in pseudos for input types * @param {String} type */ function createInputPseudo( type ) { return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; + return nodeName( elem, "input" ) && elem.type === type; }; } @@ -1011,8 +1010,8 @@ function createInputPseudo( type ) { */ function createButtonPseudo( type ) { return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return ( name === "input" || name === "button" ) && elem.type === type; + return ( nodeName( elem, "input" ) || nodeName( elem, "button" ) ) && + elem.type === type; }; } @@ -1048,14 +1047,13 @@ function createDisabledPseudo( disabled ) { } } - // Support: IE 6 - 11 + // Support: IE 6 - 11+ // Use the isDisabled shortcut property to check for disabled fieldset ancestors return elem.isDisabled === disabled || // Where there is no isDisabled, check manually - /* jshint -W018 */ elem.isDisabled !== !disabled && - inDisabledFieldset( elem ) === disabled; + inDisabledFieldset( elem ) === disabled; } return elem.disabled === disabled; @@ -1095,7 +1093,7 @@ function createPositionalPseudo( fn ) { } /** - * Checks a node for validity as a Sizzle context + * Checks a node for validity as a jQuery selector context * @param {Element|Object=} context * @returns {Element|Object|Boolean} The input node if acceptable, otherwise a falsy value */ @@ -1103,31 +1101,13 @@ function testContext( context ) { return context && typeof context.getElementsByTagName !== "undefined" && context; } -// Expose support vars for convenience -support = Sizzle.support = {}; - -/** - * Detects XML nodes - * @param {Element|Object} elem An element or a document - * @returns {Boolean} True iff elem is a non-HTML XML node - */ -isXML = Sizzle.isXML = function( elem ) { - var namespace = elem && elem.namespaceURI, - docElem = elem && ( elem.ownerDocument || elem ).documentElement; - - // Support: IE <=8 - // Assume HTML when documentElement doesn't yet exist, such as inside loading iframes - // https://bugs.jquery.com/ticket/4833 - return !rhtml.test( namespace || docElem && docElem.nodeName || "HTML" ); -}; - /** * Sets document-related variables once based on the current document - * @param {Element|Object} [doc] An element or document object to use to set the document + * @param {Element|Object} [node] An element or document object to use to set the document * @returns {Object} Returns the current document */ -setDocument = Sizzle.setDocument = function( node ) { - var hasCompare, subWindow, +function setDocument( node ) { + var subWindow, doc = node ? node.ownerDocument || node : preferredDoc; // Return early if doc is invalid or already selected @@ -1141,87 +1121,90 @@ setDocument = Sizzle.setDocument = function( node ) { // Update global variables document = doc; - docElem = document.documentElement; - documentIsHTML = !isXML( document ); + documentElement = document.documentElement; + documentIsHTML = !jQuery.isXMLDoc( document ); + + // Support: iOS 7 only, IE 9 - 11+ + // Older browsers didn't support unprefixed `matches`. + matches = documentElement.matches || + documentElement.webkitMatchesSelector || + documentElement.msMatchesSelector; // Support: IE 9 - 11+, Edge 12 - 18+ - // Accessing iframe documents after unload throws "permission denied" errors (jQuery #13936) - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - // eslint-disable-next-line eqeqeq - if ( preferredDoc != document && - ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { + // Accessing iframe documents after unload throws "permission denied" errors + // (see trac-13936). + // Limit the fix to IE & Edge Legacy; despite Edge 15+ implementing `matches`, + // all IE 9+ and Edge Legacy versions implement `msMatchesSelector` as well. + if ( documentElement.msMatchesSelector && - // Support: IE 11, Edge - if ( subWindow.addEventListener ) { - subWindow.addEventListener( "unload", unloadHandler, false ); + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + preferredDoc != document && + ( subWindow = document.defaultView ) && subWindow.top !== subWindow ) { - // Support: IE 9 - 10 only - } else if ( subWindow.attachEvent ) { - subWindow.attachEvent( "onunload", unloadHandler ); - } + // Support: IE 9 - 11+, Edge 12 - 18+ + subWindow.addEventListener( "unload", unloadHandler ); } - // Support: IE 8 - 11+, Edge 12 - 18+, Chrome <=16 - 25 only, Firefox <=3.6 - 31 only, - // Safari 4 - 5 only, Opera <=11.6 - 12.x only - // IE/Edge & older browsers don't support the :scope pseudo-class. - // Support: Safari 6.0 only - // Safari 6.0 supports :scope but it's an alias of :root there. - support.scope = assert( function( el ) { - docElem.appendChild( el ).appendChild( document.createElement( "div" ) ); - return typeof el.querySelectorAll !== "undefined" && - !el.querySelectorAll( ":scope fieldset div" ).length; + // Support: IE <10 + // Check if getElementById returns elements by name + // The broken getElementById methods don't pick up programmatically-set names, + // so use a roundabout getElementsByName test + support.getById = assert( function( el ) { + documentElement.appendChild( el ).id = jQuery.expando; + return !document.getElementsByName || + !document.getElementsByName( jQuery.expando ).length; } ); - /* Attributes - ---------------------------------------------------------------------- */ - - // Support: IE<8 - // Verify that getAttribute really returns attributes and not properties - // (excepting IE8 booleans) - support.attributes = assert( function( el ) { - el.className = "i"; - return !el.getAttribute( "className" ); + // Support: IE 9 only + // Check to see if it's possible to do matchesSelector + // on a disconnected node. + support.disconnectedMatch = assert( function( el ) { + return matches.call( el, "*" ); } ); - /* getElement(s)By* - ---------------------------------------------------------------------- */ - - // Check if getElementsByTagName("*") returns only elements - support.getElementsByTagName = assert( function( el ) { - el.appendChild( document.createComment( "" ) ); - return !el.getElementsByTagName( "*" ).length; + // Support: IE 9 - 11+, Edge 12 - 18+ + // IE/Edge don't support the :scope pseudo-class. + support.scope = assert( function() { + return document.querySelectorAll( ":scope" ); } ); - // Support: IE<9 - support.getElementsByClassName = rnative.test( document.getElementsByClassName ); - - // Support: IE<10 - // Check if getElementById returns elements by name - // The broken getElementById methods don't pick up programmatically-set names, - // so use a roundabout getElementsByName test - support.getById = assert( function( el ) { - docElem.appendChild( el ).id = expando; - return !document.getElementsByName || !document.getElementsByName( expando ).length; + // Support: Chrome 105 - 111 only, Safari 15.4 - 16.3 only + // Make sure the `:has()` argument is parsed unforgivingly. + // We include `*` in the test to detect buggy implementations that are + // _selectively_ forgiving (specifically when the list includes at least + // one valid selector). + // Note that we treat complete lack of support for `:has()` as if it were + // spec-compliant support, which is fine because use of `:has()` in such + // environments will fail in the qSA path and fall back to jQuery traversal + // anyway. + support.cssHas = assert( function() { + try { + document.querySelector( ":has(*,:jqfake)" ); + return false; + } catch ( e ) { + return true; + } } ); // ID filter and find if ( support.getById ) { - Expr.filter[ "ID" ] = function( id ) { + Expr.filter.ID = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { return elem.getAttribute( "id" ) === attrId; }; }; - Expr.find[ "ID" ] = function( id, context ) { + Expr.find.ID = function( id, context ) { if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var elem = context.getElementById( id ); return elem ? [ elem ] : []; } }; } else { - Expr.filter[ "ID" ] = function( id ) { + Expr.filter.ID = function( id ) { var attrId = id.replace( runescape, funescape ); return function( elem ) { var node = typeof elem.getAttributeNode !== "undefined" && @@ -1232,7 +1215,7 @@ setDocument = Sizzle.setDocument = function( node ) { // Support: IE 6 - 7 only // getElementById is not reliable as a find shortcut - Expr.find[ "ID" ] = function( id, context ) { + Expr.find.ID = function( id, context ) { if ( typeof context.getElementById !== "undefined" && documentIsHTML ) { var node, i, elems, elem = context.getElementById( id ); @@ -1262,40 +1245,18 @@ setDocument = Sizzle.setDocument = function( node ) { } // Tag - Expr.find[ "TAG" ] = support.getElementsByTagName ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== "undefined" ) { - return context.getElementsByTagName( tag ); - - // DocumentFragment nodes don't have gEBTN - } else if ( support.qsa ) { - return context.querySelectorAll( tag ); - } - } : - - function( tag, context ) { - var elem, - tmp = [], - i = 0, - - // By happy coincidence, a (broken) gEBTN appears on DocumentFragment nodes too - results = context.getElementsByTagName( tag ); + Expr.find.TAG = function( tag, context ) { + if ( typeof context.getElementsByTagName !== "undefined" ) { + return context.getElementsByTagName( tag ); - // Filter out possible comments - if ( tag === "*" ) { - while ( ( elem = results[ i++ ] ) ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }; + // DocumentFragment nodes don't have gEBTN + } else { + return context.querySelectorAll( tag ); + } + }; // Class - Expr.find[ "CLASS" ] = support.getElementsByClassName && function( className, context ) { + Expr.find.CLASS = function( className, context ) { if ( typeof context.getElementsByClassName !== "undefined" && documentIsHTML ) { return context.getElementsByClassName( className ); } @@ -1306,177 +1267,94 @@ setDocument = Sizzle.setDocument = function( node ) { // QSA and matchesSelector support - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - rbuggyMatches = []; - - // qSa(:focus) reports false when true (Chrome 21) - // We allow this because of a bug in IE8/9 that throws an error - // whenever `document.activeElement` is accessed on an iframe - // So, we allow :focus to pass through QSA all the time to avoid the IE error - // See https://bugs.jquery.com/ticket/13378 rbuggyQSA = []; - if ( ( support.qsa = rnative.test( document.querySelectorAll ) ) ) { - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert( function( el ) { + // Build QSA regex + // Regex strategy adopted from Diego Perini + assert( function( el ) { - var input; + var input; - // Select is set to empty string on purpose - // This is to test IE's treatment of not explicitly - // setting a boolean content attribute, - // since its presence should be enough - // https://bugs.jquery.com/ticket/12359 - docElem.appendChild( el ).innerHTML = "" + - ""; - - // Support: IE8, Opera 11-12.16 - // Nothing should be selected when empty strings follow ^= or $= or *= - // The test attribute must be unknown in Opera but "safe" for WinRT - // https://msdn.microsoft.com/en-us/library/ie/hh465388.aspx#attribute_section - if ( el.querySelectorAll( "[msallowcapture^='']" ).length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:''|\"\")" ); - } + documentElement.appendChild( el ).innerHTML = + "" + + ""; - // Support: IE8 - // Boolean attributes and "value" are not treated correctly - if ( !el.querySelectorAll( "[selected]" ).length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); - } - - // Support: Chrome<29, Android<4.4, Safari<7.0+, iOS<7.0+, PhantomJS<1.9.8+ - if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { - rbuggyQSA.push( "~=" ); - } - - // Support: IE 11+, Edge 15 - 18+ - // IE 11/Edge don't find elements on a `[name='']` query in some cases. - // Adding a temporary attribute to the document before the selection works - // around the issue. - // Interestingly, IE 10 & older don't seem to have the issue. - input = document.createElement( "input" ); - input.setAttribute( "name", "" ); - el.appendChild( input ); - if ( !el.querySelectorAll( "[name='']" ).length ) { - rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + - whitespace + "*(?:''|\"\")" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here and will not see later tests - if ( !el.querySelectorAll( ":checked" ).length ) { - rbuggyQSA.push( ":checked" ); - } - - // Support: Safari 8+, iOS 8+ - // https://bugs.webkit.org/show_bug.cgi?id=136851 - // In-page `selector#id sibling-combinator selector` fails - if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { - rbuggyQSA.push( ".#.+[+~]" ); - } - - // Support: Firefox <=3.6 - 5 only - // Old Firefox doesn't throw on a badly-escaped identifier. - el.querySelectorAll( "\\\f" ); - rbuggyQSA.push( "[\\r\\n\\f]" ); - } ); - - assert( function( el ) { - el.innerHTML = "" + - ""; - - // Support: Windows 8 Native Apps - // The type and name attributes are restricted during .innerHTML assignment - var input = document.createElement( "input" ); - input.setAttribute( "type", "hidden" ); - el.appendChild( input ).setAttribute( "name", "D" ); - - // Support: IE8 - // Enforce case-sensitivity of name attribute - if ( el.querySelectorAll( "[name=d]" ).length ) { - rbuggyQSA.push( "name" + whitespace + "*[*^$|!~]?=" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here and will not see later tests - if ( el.querySelectorAll( ":enabled" ).length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } + // Support: iOS <=7 - 8 only + // Boolean attributes and "value" are not treated correctly in some XML documents + if ( !el.querySelectorAll( "[selected]" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*(?:value|" + booleans + ")" ); + } - // Support: IE9-11+ - // IE's :disabled selector does not pick up the children of disabled fieldsets - docElem.appendChild( el ).disabled = true; - if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { - rbuggyQSA.push( ":enabled", ":disabled" ); - } + // Support: iOS <=7 - 8 only + if ( !el.querySelectorAll( "[id~=" + expando + "-]" ).length ) { + rbuggyQSA.push( "~=" ); + } - // Support: Opera 10 - 11 only - // Opera 10-11 does not throw on post-comma invalid pseudos - el.querySelectorAll( "*,:x" ); - rbuggyQSA.push( ",.*:" ); - } ); - } + // Support: iOS 8 only + // https://bugs.webkit.org/show_bug.cgi?id=136851 + // In-page `selector#id sibling-combinator selector` fails + if ( !el.querySelectorAll( "a#" + expando + "+*" ).length ) { + rbuggyQSA.push( ".#.+[+~]" ); + } - if ( ( support.matchesSelector = rnative.test( ( matches = docElem.matches || - docElem.webkitMatchesSelector || - docElem.mozMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector ) ) ) ) { + // Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+ + // In some of the document kinds, these selectors wouldn't work natively. + // This is probably OK but for backwards compatibility we want to maintain + // handling them through jQuery traversal in jQuery 3.x. + if ( !el.querySelectorAll( ":checked" ).length ) { + rbuggyQSA.push( ":checked" ); + } - assert( function( el ) { + // Support: Windows 8 Native Apps + // The type and name attributes are restricted during .innerHTML assignment + input = document.createElement( "input" ); + input.setAttribute( "type", "hidden" ); + el.appendChild( input ).setAttribute( "name", "D" ); + + // Support: IE 9 - 11+ + // IE's :disabled selector does not pick up the children of disabled fieldsets + // Support: Chrome <=105+, Firefox <=104+, Safari <=15.4+ + // In some of the document kinds, these selectors wouldn't work natively. + // This is probably OK but for backwards compatibility we want to maintain + // handling them through jQuery traversal in jQuery 3.x. + documentElement.appendChild( el ).disabled = true; + if ( el.querySelectorAll( ":disabled" ).length !== 2 ) { + rbuggyQSA.push( ":enabled", ":disabled" ); + } + + // Support: IE 11+, Edge 15 - 18+ + // IE 11/Edge don't find elements on a `[name='']` query in some cases. + // Adding a temporary attribute to the document before the selection works + // around the issue. + // Interestingly, IE 10 & older don't seem to have the issue. + input = document.createElement( "input" ); + input.setAttribute( "name", "" ); + el.appendChild( input ); + if ( !el.querySelectorAll( "[name='']" ).length ) { + rbuggyQSA.push( "\\[" + whitespace + "*name" + whitespace + "*=" + + whitespace + "*(?:''|\"\")" ); + } + } ); - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - support.disconnectedMatch = matches.call( el, "*" ); + if ( !support.cssHas ) { - // This should fail with an exception - // Gecko does not error, returns false instead - matches.call( el, "[s!='']:x" ); - rbuggyMatches.push( "!=", pseudos ); - } ); + // Support: Chrome 105 - 110+, Safari 15.4 - 16.3+ + // Our regular `try-catch` mechanism fails to detect natively-unsupported + // pseudo-classes inside `:has()` (such as `:has(:contains("Foo"))`) + // in browsers that parse the `:has()` argument as a forgiving selector list. + // https://drafts.csswg.org/selectors/#relational now requires the argument + // to be parsed unforgivingly, but browsers have not yet fully adjusted. + rbuggyQSA.push( ":has" ); } rbuggyQSA = rbuggyQSA.length && new RegExp( rbuggyQSA.join( "|" ) ); - rbuggyMatches = rbuggyMatches.length && new RegExp( rbuggyMatches.join( "|" ) ); - - /* Contains - ---------------------------------------------------------------------- */ - hasCompare = rnative.test( docElem.compareDocumentPosition ); - - // Element contains another - // Purposefully self-exclusive - // As in, an element does not contain itself - contains = hasCompare || rnative.test( docElem.contains ) ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - ) ); - } : - function( a, b ) { - if ( b ) { - while ( ( b = b.parentNode ) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; /* Sorting ---------------------------------------------------------------------- */ // Document order sorting - sortOrder = hasCompare ? - function( a, b ) { + sortOrder = function( a, b ) { // Flag for duplicate removal if ( a === b ) { @@ -1510,8 +1388,8 @@ setDocument = Sizzle.setDocument = function( node ) { // IE/Edge sometimes throw a "Permission denied" error when strict-comparing // two documents; shallow comparisons work. // eslint-disable-next-line eqeqeq - if ( a == document || a.ownerDocument == preferredDoc && - contains( preferredDoc, a ) ) { + if ( a === document || a.ownerDocument == preferredDoc && + find.contains( preferredDoc, a ) ) { return -1; } @@ -1519,100 +1397,33 @@ setDocument = Sizzle.setDocument = function( node ) { // IE/Edge sometimes throw a "Permission denied" error when strict-comparing // two documents; shallow comparisons work. // eslint-disable-next-line eqeqeq - if ( b == document || b.ownerDocument == preferredDoc && - contains( preferredDoc, b ) ) { + if ( b === document || b.ownerDocument == preferredDoc && + find.contains( preferredDoc, b ) ) { return 1; } // Maintain original order return sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : + ( indexOf.call( sortInput, a ) - indexOf.call( sortInput, b ) ) : 0; } return compare & 4 ? -1 : 1; - } : - function( a, b ) { - - // Exit early if the nodes are identical - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - var cur, - i = 0, - aup = a.parentNode, - bup = b.parentNode, - ap = [ a ], - bp = [ b ]; - - // Parentless nodes are either documents or disconnected - if ( !aup || !bup ) { - - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - /* eslint-disable eqeqeq */ - return a == document ? -1 : - b == document ? 1 : - /* eslint-enable eqeqeq */ - aup ? -1 : - bup ? 1 : - sortInput ? - ( indexOf( sortInput, a ) - indexOf( sortInput, b ) ) : - 0; - - // If the nodes are siblings, we can do a quick check - } else if ( aup === bup ) { - return siblingCheck( a, b ); - } - - // Otherwise we need full lists of their ancestors for comparison - cur = a; - while ( ( cur = cur.parentNode ) ) { - ap.unshift( cur ); - } - cur = b; - while ( ( cur = cur.parentNode ) ) { - bp.unshift( cur ); - } - - // Walk down the tree looking for a discrepancy - while ( ap[ i ] === bp[ i ] ) { - i++; - } - - return i ? - - // Do a sibling check if the nodes have a common ancestor - siblingCheck( ap[ i ], bp[ i ] ) : - - // Otherwise nodes in our document sort first - // Support: IE 11+, Edge 17 - 18+ - // IE/Edge sometimes throw a "Permission denied" error when strict-comparing - // two documents; shallow comparisons work. - /* eslint-disable eqeqeq */ - ap[ i ] == preferredDoc ? -1 : - bp[ i ] == preferredDoc ? 1 : - /* eslint-enable eqeqeq */ - 0; }; return document; -}; +} -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); +find.matches = function( expr, elements ) { + return find( expr, null, null, elements ); }; -Sizzle.matchesSelector = function( elem, expr ) { +find.matchesSelector = function( elem, expr ) { setDocument( elem ); - if ( support.matchesSelector && documentIsHTML && + if ( documentIsHTML && !nonnativeSelectorCache[ expr + " " ] && - ( !rbuggyMatches || !rbuggyMatches.test( expr ) ) && - ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { + ( !rbuggyQSA || !rbuggyQSA.test( expr ) ) ) { try { var ret = matches.call( elem, expr ); @@ -1620,9 +1431,9 @@ Sizzle.matchesSelector = function( elem, expr ) { // IE 9's matchesSelector returns false on disconnected nodes if ( ret || support.disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { + // As well, disconnected nodes are said to be in a document + // fragment in IE 9 + elem.document && elem.document.nodeType !== 11 ) { return ret; } } catch ( e ) { @@ -1630,10 +1441,10 @@ Sizzle.matchesSelector = function( elem, expr ) { } } - return Sizzle( expr, document, null, [ elem ] ).length > 0; + return find( expr, document, null, [ elem ] ).length > 0; }; -Sizzle.contains = function( context, elem ) { +find.contains = function( context, elem ) { // Set document vars if needed // Support: IE 11+, Edge 17 - 18+ @@ -1643,10 +1454,11 @@ Sizzle.contains = function( context, elem ) { if ( ( context.ownerDocument || context ) != document ) { setDocument( context ); } - return contains( context, elem ); + return jQuery.contains( context, elem ); }; -Sizzle.attr = function( elem, name ) { + +find.attr = function( elem, name ) { // Set document vars if needed // Support: IE 11+, Edge 17 - 18+ @@ -1659,25 +1471,19 @@ Sizzle.attr = function( elem, name ) { var fn = Expr.attrHandle[ name.toLowerCase() ], - // Don't get fooled by Object.prototype properties (jQuery #13807) + // Don't get fooled by Object.prototype properties (see trac-13807) val = fn && hasOwn.call( Expr.attrHandle, name.toLowerCase() ) ? fn( elem, name, !documentIsHTML ) : undefined; - return val !== undefined ? - val : - support.attributes || !documentIsHTML ? - elem.getAttribute( name ) : - ( val = elem.getAttributeNode( name ) ) && val.specified ? - val.value : - null; -}; + if ( val !== undefined ) { + return val; + } -Sizzle.escape = function( sel ) { - return ( sel + "" ).replace( rcssescape, fcssescape ); + return elem.getAttribute( name ); }; -Sizzle.error = function( msg ) { +find.error = function( msg ) { throw new Error( "Syntax error, unrecognized expression: " + msg ); }; @@ -1685,16 +1491,20 @@ Sizzle.error = function( msg ) { * Document sorting and removing duplicates * @param {ArrayLike} results */ -Sizzle.uniqueSort = function( results ) { +jQuery.uniqueSort = function( results ) { var elem, duplicates = [], j = 0, i = 0; // Unless we *know* we can detect duplicates, assume their presence - hasDuplicate = !support.detectDuplicates; - sortInput = !support.sortStable && results.slice( 0 ); - results.sort( sortOrder ); + // + // Support: Android <=4.0+ + // Testing for detecting duplicates is unpredictable so instead assume we can't + // depend on duplicate detection in all browsers without a stable sort. + hasDuplicate = !support.sortStable; + sortInput = !support.sortStable && slice.call( results, 0 ); + sort.call( results, sortOrder ); if ( hasDuplicate ) { while ( ( elem = results[ i++ ] ) ) { @@ -1703,7 +1513,7 @@ Sizzle.uniqueSort = function( results ) { } } while ( j-- ) { - results.splice( duplicates[ j ], 1 ); + splice.call( results, duplicates[ j ], 1 ); } } @@ -1714,47 +1524,11 @@ Sizzle.uniqueSort = function( results ) { return results; }; -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( !nodeType ) { - - // If no nodeType, this is expected to be an array - while ( ( node = elem[ i++ ] ) ) { - - // Do not traverse comment nodes - ret += getText( node ); - } - } else if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - - // Use textContent for elements - // innerText usage removed for consistency of new lines (jQuery #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - - // Do not include comment or processing instruction nodes - - return ret; +jQuery.fn.uniqueSort = function() { + return this.pushStack( jQuery.uniqueSort( slice.apply( this ) ) ); }; -Expr = Sizzle.selectors = { +Expr = jQuery.expr = { // Can be adjusted by the user cacheLength: 50, @@ -1775,12 +1549,12 @@ Expr = Sizzle.selectors = { }, preFilter: { - "ATTR": function( match ) { + ATTR: function( match ) { match[ 1 ] = match[ 1 ].replace( runescape, funescape ); // Move the given value to match[3] whether quoted or unquoted - match[ 3 ] = ( match[ 3 ] || match[ 4 ] || - match[ 5 ] || "" ).replace( runescape, funescape ); + match[ 3 ] = ( match[ 3 ] || match[ 4 ] || match[ 5 ] || "" ) + .replace( runescape, funescape ); if ( match[ 2 ] === "~=" ) { match[ 3 ] = " " + match[ 3 ] + " "; @@ -1789,7 +1563,7 @@ Expr = Sizzle.selectors = { return match.slice( 0, 4 ); }, - "CHILD": function( match ) { + CHILD: function( match ) { /* matches from matchExpr["CHILD"] 1 type (only|nth|...) @@ -1807,29 +1581,30 @@ Expr = Sizzle.selectors = { // nth-* requires argument if ( !match[ 3 ] ) { - Sizzle.error( match[ 0 ] ); + find.error( match[ 0 ] ); } // numeric x and y parameters for Expr.filter.CHILD // remember that false/true cast respectively to 0/1 match[ 4 ] = +( match[ 4 ] ? match[ 5 ] + ( match[ 6 ] || 1 ) : - 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) ); + 2 * ( match[ 3 ] === "even" || match[ 3 ] === "odd" ) + ); match[ 5 ] = +( ( match[ 7 ] + match[ 8 ] ) || match[ 3 ] === "odd" ); - // other types prohibit arguments + // other types prohibit arguments } else if ( match[ 3 ] ) { - Sizzle.error( match[ 0 ] ); + find.error( match[ 0 ] ); } return match; }, - "PSEUDO": function( match ) { + PSEUDO: function( match ) { var excess, unquoted = !match[ 6 ] && match[ 2 ]; - if ( matchExpr[ "CHILD" ].test( match[ 0 ] ) ) { + if ( matchExpr.CHILD.test( match[ 0 ] ) ) { return null; } @@ -1858,36 +1633,36 @@ Expr = Sizzle.selectors = { filter: { - "TAG": function( nodeNameSelector ) { - var nodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); + TAG: function( nodeNameSelector ) { + var expectedNodeName = nodeNameSelector.replace( runescape, funescape ).toLowerCase(); return nodeNameSelector === "*" ? function() { return true; } : function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; + return nodeName( elem, expectedNodeName ); }; }, - "CLASS": function( className ) { + CLASS: function( className ) { var pattern = classCache[ className + " " ]; return pattern || - ( pattern = new RegExp( "(^|" + whitespace + - ")" + className + "(" + whitespace + "|$)" ) ) && classCache( - className, function( elem ) { - return pattern.test( - typeof elem.className === "string" && elem.className || - typeof elem.getAttribute !== "undefined" && - elem.getAttribute( "class" ) || - "" - ); + ( pattern = new RegExp( "(^|" + whitespace + ")" + className + + "(" + whitespace + "|$)" ) ) && + classCache( className, function( elem ) { + return pattern.test( + typeof elem.className === "string" && elem.className || + typeof elem.getAttribute !== "undefined" && + elem.getAttribute( "class" ) || + "" + ); } ); }, - "ATTR": function( name, operator, check ) { + ATTR: function( name, operator, check ) { return function( elem ) { - var result = Sizzle.attr( elem, name ); + var result = find.attr( elem, name ); if ( result == null ) { return operator === "!="; @@ -1898,22 +1673,34 @@ Expr = Sizzle.selectors = { result += ""; - /* eslint-disable max-len */ - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.slice( -check.length ) === check : - operator === "~=" ? ( " " + result.replace( rwhitespace, " " ) + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.slice( 0, check.length + 1 ) === check + "-" : - false; - /* eslint-enable max-len */ + if ( operator === "=" ) { + return result === check; + } + if ( operator === "!=" ) { + return result !== check; + } + if ( operator === "^=" ) { + return check && result.indexOf( check ) === 0; + } + if ( operator === "*=" ) { + return check && result.indexOf( check ) > -1; + } + if ( operator === "$=" ) { + return check && result.slice( -check.length ) === check; + } + if ( operator === "~=" ) { + return ( " " + result.replace( rwhitespace, " " ) + " " ) + .indexOf( check ) > -1; + } + if ( operator === "|=" ) { + return result === check || result.slice( 0, check.length + 1 ) === check + "-"; + } + return false; }; }, - "CHILD": function( type, what, _argument, first, last ) { + CHILD: function( type, what, _argument, first, last ) { var simple = type.slice( 0, 3 ) !== "nth", forward = type.slice( -4 ) !== "last", ofType = what === "of-type"; @@ -1926,7 +1713,7 @@ Expr = Sizzle.selectors = { } : function( elem, _context, xml ) { - var cache, uniqueCache, outerCache, node, nodeIndex, start, + var cache, outerCache, node, nodeIndex, start, dir = simple !== forward ? "nextSibling" : "previousSibling", parent = elem.parentNode, name = ofType && elem.nodeName.toLowerCase(), @@ -1941,7 +1728,7 @@ Expr = Sizzle.selectors = { node = elem; while ( ( node = node[ dir ] ) ) { if ( ofType ? - node.nodeName.toLowerCase() === name : + nodeName( node, name ) : node.nodeType === 1 ) { return false; @@ -1960,17 +1747,8 @@ Expr = Sizzle.selectors = { if ( forward && useCache ) { // Seek `elem` from a previously-cached index - - // ...in a gzip-friendly way - node = parent; - outerCache = node[ expando ] || ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - cache = uniqueCache[ type ] || []; + outerCache = parent[ expando ] || ( parent[ expando ] = {} ); + cache = outerCache[ type ] || []; nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; diff = nodeIndex && cache[ 2 ]; node = nodeIndex && parent.childNodes[ nodeIndex ]; @@ -1982,7 +1760,7 @@ Expr = Sizzle.selectors = { // When found, cache indexes on `parent` and break if ( node.nodeType === 1 && ++diff && node === elem ) { - uniqueCache[ type ] = [ dirruns, nodeIndex, diff ]; + outerCache[ type ] = [ dirruns, nodeIndex, diff ]; break; } } @@ -1991,17 +1769,8 @@ Expr = Sizzle.selectors = { // Use previously-cached element index if available if ( useCache ) { - - // ...in a gzip-friendly way - node = elem; - outerCache = node[ expando ] || ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - cache = uniqueCache[ type ] || []; + outerCache = elem[ expando ] || ( elem[ expando ] = {} ); + cache = outerCache[ type ] || []; nodeIndex = cache[ 0 ] === dirruns && cache[ 1 ]; diff = nodeIndex; } @@ -2015,7 +1784,7 @@ Expr = Sizzle.selectors = { ( diff = nodeIndex = 0 ) || start.pop() ) ) { if ( ( ofType ? - node.nodeName.toLowerCase() === name : + nodeName( node, name ) : node.nodeType === 1 ) && ++diff ) { @@ -2023,13 +1792,7 @@ Expr = Sizzle.selectors = { if ( useCache ) { outerCache = node[ expando ] || ( node[ expando ] = {} ); - - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ node.uniqueID ] || - ( outerCache[ node.uniqueID ] = {} ); - - uniqueCache[ type ] = [ dirruns, diff ]; + outerCache[ type ] = [ dirruns, diff ]; } if ( node === elem ) { @@ -2047,19 +1810,19 @@ Expr = Sizzle.selectors = { }; }, - "PSEUDO": function( pseudo, argument ) { + PSEUDO: function( pseudo, argument ) { // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes + // https://www.w3.org/TR/selectors/#pseudo-classes // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters // Remember that setFilters inherits from pseudos var args, fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); + find.error( "unsupported pseudo: " + pseudo ); // The user may use createPseudo to indicate that // arguments are needed to create the filter function - // just as Sizzle does + // just as jQuery does if ( fn[ expando ] ) { return fn( argument ); } @@ -2073,7 +1836,7 @@ Expr = Sizzle.selectors = { matched = fn( seed, argument ), i = matched.length; while ( i-- ) { - idx = indexOf( seed, matched[ i ] ); + idx = indexOf.call( seed, matched[ i ] ); seed[ idx ] = !( matches[ idx ] = matched[ i ] ); } } ) : @@ -2089,14 +1852,14 @@ Expr = Sizzle.selectors = { pseudos: { // Potentially complex pseudos - "not": markFunction( function( selector ) { + not: markFunction( function( selector ) { // Trim the selector passed to compile // to avoid treating leading and trailing // spaces as combinators var input = [], results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); + matcher = compile( selector.replace( rtrimCSS, "$1" ) ); return matcher[ expando ] ? markFunction( function( seed, matches, _context, xml ) { @@ -2115,22 +1878,23 @@ Expr = Sizzle.selectors = { input[ 0 ] = elem; matcher( input, null, xml, results ); - // Don't keep the element (issue #299) + // Don't keep the element + // (see https://github.com/jquery/sizzle/issues/299) input[ 0 ] = null; return !results.pop(); }; } ), - "has": markFunction( function( selector ) { + has: markFunction( function( selector ) { return function( elem ) { - return Sizzle( selector, elem ).length > 0; + return find( selector, elem ).length > 0; }; } ), - "contains": markFunction( function( text ) { + contains: markFunction( function( text ) { text = text.replace( runescape, funescape ); return function( elem ) { - return ( elem.textContent || getText( elem ) ).indexOf( text ) > -1; + return ( elem.textContent || jQuery.text( elem ) ).indexOf( text ) > -1; }; } ), @@ -2140,12 +1904,12 @@ Expr = Sizzle.selectors = { // or beginning with the identifier C immediately followed by "-". // The matching of C against the element's language value is performed case-insensitively. // The identifier C does not have to be a valid language name." - // http://www.w3.org/TR/selectors/#lang-pseudo - "lang": markFunction( function( lang ) { + // https://www.w3.org/TR/selectors/#lang-pseudo + lang: markFunction( function( lang ) { // lang value must be a valid identifier if ( !ridentifier.test( lang || "" ) ) { - Sizzle.error( "unsupported lang: " + lang ); + find.error( "unsupported lang: " + lang ); } lang = lang.replace( runescape, funescape ).toLowerCase(); return function( elem ) { @@ -2164,38 +1928,39 @@ Expr = Sizzle.selectors = { } ), // Miscellaneous - "target": function( elem ) { + target: function( elem ) { var hash = window.location && window.location.hash; return hash && hash.slice( 1 ) === elem.id; }, - "root": function( elem ) { - return elem === docElem; + root: function( elem ) { + return elem === documentElement; }, - "focus": function( elem ) { - return elem === document.activeElement && - ( !document.hasFocus || document.hasFocus() ) && + focus: function( elem ) { + return elem === safeActiveElement() && + document.hasFocus() && !!( elem.type || elem.href || ~elem.tabIndex ); }, // Boolean properties - "enabled": createDisabledPseudo( false ), - "disabled": createDisabledPseudo( true ), + enabled: createDisabledPseudo( false ), + disabled: createDisabledPseudo( true ), - "checked": function( elem ) { + checked: function( elem ) { // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return ( nodeName === "input" && !!elem.checked ) || - ( nodeName === "option" && !!elem.selected ); + // https://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked + return ( nodeName( elem, "input" ) && !!elem.checked ) || + ( nodeName( elem, "option" ) && !!elem.selected ); }, - "selected": function( elem ) { + selected: function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly + // Support: IE <=11+ + // Accessing the selectedIndex property + // forces the browser to treat the default option as + // selected when in an optgroup. if ( elem.parentNode ) { // eslint-disable-next-line no-unused-expressions elem.parentNode.selectedIndex; @@ -2205,9 +1970,9 @@ Expr = Sizzle.selectors = { }, // Contents - "empty": function( elem ) { + empty: function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo + // https://www.w3.org/TR/selectors/#empty-pseudo // :empty is negated by element (1) or content nodes (text: 3; cdata: 4; entity ref: 5), // but not by others (comment: 8; processing instruction: 7; etc.) // nodeType < 6 works because attributes (2) do not appear as children @@ -2219,49 +1984,49 @@ Expr = Sizzle.selectors = { return true; }, - "parent": function( elem ) { - return !Expr.pseudos[ "empty" ]( elem ); + parent: function( elem ) { + return !Expr.pseudos.empty( elem ); }, // Element/input types - "header": function( elem ) { + header: function( elem ) { return rheader.test( elem.nodeName ); }, - "input": function( elem ) { + input: function( elem ) { return rinputs.test( elem.nodeName ); }, - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; + button: function( elem ) { + return nodeName( elem, "input" ) && elem.type === "button" || + nodeName( elem, "button" ); }, - "text": function( elem ) { + text: function( elem ) { var attr; - return elem.nodeName.toLowerCase() === "input" && - elem.type === "text" && + return nodeName( elem, "input" ) && elem.type === "text" && - // Support: IE<8 - // New HTML5 attribute values (e.g., "search") appear with elem.type === "text" + // Support: IE <10 only + // New HTML5 attribute values (e.g., "search") appear + // with elem.type === "text" ( ( attr = elem.getAttribute( "type" ) ) == null || attr.toLowerCase() === "text" ); }, // Position-in-collection - "first": createPositionalPseudo( function() { + first: createPositionalPseudo( function() { return [ 0 ]; } ), - "last": createPositionalPseudo( function( _matchIndexes, length ) { + last: createPositionalPseudo( function( _matchIndexes, length ) { return [ length - 1 ]; } ), - "eq": createPositionalPseudo( function( _matchIndexes, length, argument ) { + eq: createPositionalPseudo( function( _matchIndexes, length, argument ) { return [ argument < 0 ? argument + length : argument ]; } ), - "even": createPositionalPseudo( function( matchIndexes, length ) { + even: createPositionalPseudo( function( matchIndexes, length ) { var i = 0; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); @@ -2269,7 +2034,7 @@ Expr = Sizzle.selectors = { return matchIndexes; } ), - "odd": createPositionalPseudo( function( matchIndexes, length ) { + odd: createPositionalPseudo( function( matchIndexes, length ) { var i = 1; for ( ; i < length; i += 2 ) { matchIndexes.push( i ); @@ -2277,19 +2042,24 @@ Expr = Sizzle.selectors = { return matchIndexes; } ), - "lt": createPositionalPseudo( function( matchIndexes, length, argument ) { - var i = argument < 0 ? - argument + length : - argument > length ? - length : - argument; + lt: createPositionalPseudo( function( matchIndexes, length, argument ) { + var i; + + if ( argument < 0 ) { + i = argument + length; + } else if ( argument > length ) { + i = length; + } else { + i = argument; + } + for ( ; --i >= 0; ) { matchIndexes.push( i ); } return matchIndexes; } ), - "gt": createPositionalPseudo( function( matchIndexes, length, argument ) { + gt: createPositionalPseudo( function( matchIndexes, length, argument ) { var i = argument < 0 ? argument + length : argument; for ( ; ++i < length; ) { matchIndexes.push( i ); @@ -2299,7 +2069,7 @@ Expr = Sizzle.selectors = { } }; -Expr.pseudos[ "nth" ] = Expr.pseudos[ "eq" ]; +Expr.pseudos.nth = Expr.pseudos.eq; // Add button/input type pseudos for ( i in { radio: true, checkbox: true, file: true, password: true, image: true } ) { @@ -2314,7 +2084,7 @@ function setFilters() {} setFilters.prototype = Expr.filters = Expr.pseudos; Expr.setFilters = new setFilters(); -tokenize = Sizzle.tokenize = function( selector, parseOnly ) { +function tokenize( selector, parseOnly ) { var matched, match, tokens, type, soFar, groups, preFilters, cached = tokenCache[ selector + " " ]; @@ -2342,13 +2112,13 @@ tokenize = Sizzle.tokenize = function( selector, parseOnly ) { matched = false; // Combinators - if ( ( match = rcombinators.exec( soFar ) ) ) { + if ( ( match = rleadingCombinator.exec( soFar ) ) ) { matched = match.shift(); tokens.push( { value: matched, // Cast descendant combinators to space - type: match[ 0 ].replace( rtrim, " " ) + type: match[ 0 ].replace( rtrimCSS, " " ) } ); soFar = soFar.slice( matched.length ); } @@ -2375,14 +2145,16 @@ tokenize = Sizzle.tokenize = function( selector, parseOnly ) { // Return the length of the invalid excess // if we're just parsing // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : + if ( parseOnly ) { + return soFar.length; + } - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -}; + return soFar ? + find.error( selector ) : + + // Cache the tokens + tokenCache( selector, groups ).slice( 0 ); +} function toSelector( tokens ) { var i = 0, @@ -2415,7 +2187,7 @@ function addCombinator( matcher, combinator, base ) { // Check against all ancestor/preceding elements function( elem, context, xml ) { - var oldCache, uniqueCache, outerCache, + var oldCache, outerCache, newCache = [ dirruns, doneName ]; // We can't set arbitrary data on XML nodes, so they don't benefit from combinator caching @@ -2432,14 +2204,9 @@ function addCombinator( matcher, combinator, base ) { if ( elem.nodeType === 1 || checkNonElements ) { outerCache = elem[ expando ] || ( elem[ expando ] = {} ); - // Support: IE <9 only - // Defend against cloned attroperties (jQuery gh-1709) - uniqueCache = outerCache[ elem.uniqueID ] || - ( outerCache[ elem.uniqueID ] = {} ); - - if ( skip && skip === elem.nodeName.toLowerCase() ) { + if ( skip && nodeName( elem, skip ) ) { elem = elem[ dir ] || elem; - } else if ( ( oldCache = uniqueCache[ key ] ) && + } else if ( ( oldCache = outerCache[ key ] ) && oldCache[ 0 ] === dirruns && oldCache[ 1 ] === doneName ) { // Assign to newCache so results back-propagate to previous elements @@ -2447,7 +2214,7 @@ function addCombinator( matcher, combinator, base ) { } else { // Reuse newcache so results back-propagate to previous elements - uniqueCache[ key ] = newCache; + outerCache[ key ] = newCache; // A match means we're done; a fail means we have to keep checking if ( ( newCache[ 2 ] = matcher( elem, context, xml ) ) ) { @@ -2479,7 +2246,7 @@ function multipleContexts( selector, contexts, results ) { var i = 0, len = contexts.length; for ( ; i < len; i++ ) { - Sizzle( selector, contexts[ i ], results ); + find( selector, contexts[ i ], results ); } return results; } @@ -2513,38 +2280,37 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS postFinder = setMatcher( postFinder, postSelector ); } return markFunction( function( seed, results, context, xml ) { - var temp, i, elem, + var temp, i, elem, matcherOut, preMap = [], postMap = [], preexisting = results.length, // Get initial elements from seed or context - elems = seed || multipleContexts( - selector || "*", - context.nodeType ? [ context ] : context, - [] - ), + elems = seed || + multipleContexts( selector || "*", + context.nodeType ? [ context ] : context, [] ), // Prefilter to get matcher input, preserving a map for seed-results synchronization matcherIn = preFilter && ( seed || !selector ) ? condense( elems, preMap, preFilter, context, xml ) : - elems, + elems; - matcherOut = matcher ? + if ( matcher ) { - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? + // If we have a postFinder, or filtered seed, or non-seed postFilter + // or preexisting results, + matcherOut = postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - // ...intermediate processing is necessary - [] : + // ...intermediate processing is necessary + [] : - // ...otherwise use results directly - results : - matcherIn; + // ...otherwise use results directly + results; - // Find primary matches - if ( matcher ) { + // Find primary matches matcher( matcherIn, matcherOut, context, xml ); + } else { + matcherOut = matcherIn; } // Apply postFilter @@ -2582,7 +2348,7 @@ function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postS i = matcherOut.length; while ( i-- ) { if ( ( elem = matcherOut[ i ] ) && - ( temp = postFinder ? indexOf( seed, elem ) : preMap[ i ] ) > -1 ) { + ( temp = postFinder ? indexOf.call( seed, elem ) : preMap[ i ] ) > -1 ) { seed[ temp ] = !( results[ temp ] = elem ); } @@ -2617,15 +2383,21 @@ function matcherFromTokens( tokens ) { return elem === checkContext; }, implicitRelative, true ), matchAnyContext = addCombinator( function( elem ) { - return indexOf( checkContext, elem ) > -1; + return indexOf.call( checkContext, elem ) > -1; }, implicitRelative, true ), matchers = [ function( elem, context, xml ) { - var ret = ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( + + // Support: IE 11+, Edge 17 - 18+ + // IE/Edge sometimes throw a "Permission denied" error when strict-comparing + // two documents; shallow comparisons work. + // eslint-disable-next-line eqeqeq + var ret = ( !leadingRelative && ( xml || context != outermostContext ) ) || ( ( checkContext = context ).nodeType ? matchContext( elem, context, xml ) : matchAnyContext( elem, context, xml ) ); - // Avoid hanging onto element (issue #299) + // Avoid hanging onto element + // (see https://github.com/jquery/sizzle/issues/299) checkContext = null; return ret; } ]; @@ -2650,11 +2422,10 @@ function matcherFromTokens( tokens ) { i > 1 && elementMatcher( matchers ), i > 1 && toSelector( - // If the preceding token was a descendant combinator, insert an implicit any-element `*` - tokens - .slice( 0, i - 1 ) - .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) - ).replace( rtrim, "$1" ), + // If the preceding token was a descendant combinator, insert an implicit any-element `*` + tokens.slice( 0, i - 1 ) + .concat( { value: tokens[ i - 2 ].type === " " ? "*" : "" } ) + ).replace( rtrimCSS, "$1" ), matcher, i < j && matcherFromTokens( tokens.slice( i, j ) ), j < len && matcherFromTokens( ( tokens = tokens.slice( j ) ) ), @@ -2680,7 +2451,7 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { contextBackup = outermostContext, // We must always have either seed elements or outermost context - elems = seed || byElement && Expr.find[ "TAG" ]( "*", outermost ), + elems = seed || byElement && Expr.find.TAG( "*", outermost ), // Use integer dirruns iff this is the outermost matcher dirrunsUnique = ( dirruns += contextBackup == null ? 1 : Math.random() || 0.1 ), @@ -2696,8 +2467,9 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { } // Add elements passing elementMatchers directly to results - // Support: IE<9, Safari - // Tolerate NodeList properties (IE: "length"; Safari: ) matching elements by id + // Support: iOS <=7 - 9 only + // Tolerate NodeList properties (IE: "length"; Safari: ) matching + // elements by id. (see trac-14142) for ( ; i !== len && ( elem = elems[ i ] ) != null; i++ ) { if ( byElement && elem ) { j = 0; @@ -2712,7 +2484,7 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { } while ( ( matcher = elementMatchers[ j++ ] ) ) { if ( matcher( elem, context || document, xml ) ) { - results.push( elem ); + push.call( results, elem ); break; } } @@ -2775,7 +2547,7 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { if ( outermost && !seed && setMatched.length > 0 && ( matchedCount + setMatchers.length ) > 1 ) { - Sizzle.uniqueSort( results ); + jQuery.uniqueSort( results ); } } @@ -2793,7 +2565,7 @@ function matcherFromGroupMatchers( elementMatchers, setMatchers ) { superMatcher; } -compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { +function compile( selector, match /* Internal Use Only */ ) { var i, setMatchers = [], elementMatchers = [], @@ -2816,27 +2588,25 @@ compile = Sizzle.compile = function( selector, match /* Internal Use Only */ ) { } // Cache the compiled function - cached = compilerCache( - selector, - matcherFromGroupMatchers( elementMatchers, setMatchers ) - ); + cached = compilerCache( selector, + matcherFromGroupMatchers( elementMatchers, setMatchers ) ); // Save selector and tokenization cached.selector = selector; } return cached; -}; +} /** - * A low-level selection function that works with Sizzle's compiled + * A low-level selection function that works with jQuery's compiled * selector functions * @param {String|Function} selector A selector or a pre-compiled - * selector function built with Sizzle.compile + * selector function built with jQuery selector compile * @param {Element} context * @param {Array} [results] * @param {Array} [seed] A set of elements to match against */ -select = Sizzle.select = function( selector, context, results, seed ) { +function select( selector, context, results, seed ) { var i, tokens, token, type, find, compiled = typeof selector === "function" && selector, match = !seed && tokenize( ( selector = compiled.selector || selector ) ); @@ -2850,10 +2620,12 @@ select = Sizzle.select = function( selector, context, results, seed ) { // Reduce context if the leading compound selector is an ID tokens = match[ 0 ] = match[ 0 ].slice( 0 ); if ( tokens.length > 2 && ( token = tokens[ 0 ] ).type === "ID" && - context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { + context.nodeType === 9 && documentIsHTML && Expr.relative[ tokens[ 1 ].type ] ) { - context = ( Expr.find[ "ID" ]( token.matches[ 0 ] - .replace( runescape, funescape ), context ) || [] )[ 0 ]; + context = ( Expr.find.ID( + token.matches[ 0 ].replace( runescape, funescape ), + context + ) || [] )[ 0 ]; if ( !context ) { return results; @@ -2866,7 +2638,7 @@ select = Sizzle.select = function( selector, context, results, seed ) { } // Fetch a seed set for right-to-left matching - i = matchExpr[ "needsContext" ].test( selector ) ? 0 : tokens.length; + i = matchExpr.needsContext.test( selector ) ? 0 : tokens.length; while ( i-- ) { token = tokens[ i ]; @@ -2879,8 +2651,8 @@ select = Sizzle.select = function( selector, context, results, seed ) { // Search, expanding context for leading sibling combinators if ( ( seed = find( token.matches[ 0 ].replace( runescape, funescape ), - rsibling.test( tokens[ 0 ].type ) && testContext( context.parentNode ) || - context + rsibling.test( tokens[ 0 ].type ) && + testContext( context.parentNode ) || context ) ) ) { // If seed is empty or no tokens remain, we can return early @@ -2907,21 +2679,18 @@ select = Sizzle.select = function( selector, context, results, seed ) { !context || rsibling.test( selector ) && testContext( context.parentNode ) || context ); return results; -}; +} // One-time assignments +// Support: Android <=4.0 - 4.1+ // Sort stability support.sortStable = expando.split( "" ).sort( sortOrder ).join( "" ) === expando; -// Support: Chrome 14-35+ -// Always assume duplicates if they aren't passed to the comparison function -support.detectDuplicates = !!hasDuplicate; - // Initialize against the default document setDocument(); -// Support: Webkit<537.32 - Safari 6.0.3/Chrome 25 (fixed in Chrome 27) +// Support: Android <=4.0 - 4.1+ // Detached nodes confoundingly follow *each other* support.sortDetached = assert( function( el ) { @@ -2929,68 +2698,29 @@ support.sortDetached = assert( function( el ) { return el.compareDocumentPosition( document.createElement( "fieldset" ) ) & 1; } ); -// Support: IE<8 -// Prevent attribute/property "interpolation" -// https://msdn.microsoft.com/en-us/library/ms536429%28VS.85%29.aspx -if ( !assert( function( el ) { - el.innerHTML = ""; - return el.firstChild.getAttribute( "href" ) === "#"; -} ) ) { - addHandle( "type|href|height|width", function( elem, name, isXML ) { - if ( !isXML ) { - return elem.getAttribute( name, name.toLowerCase() === "type" ? 1 : 2 ); - } - } ); -} - -// Support: IE<9 -// Use defaultValue in place of getAttribute("value") -if ( !support.attributes || !assert( function( el ) { - el.innerHTML = ""; - el.firstChild.setAttribute( "value", "" ); - return el.firstChild.getAttribute( "value" ) === ""; -} ) ) { - addHandle( "value", function( elem, _name, isXML ) { - if ( !isXML && elem.nodeName.toLowerCase() === "input" ) { - return elem.defaultValue; - } - } ); -} - -// Support: IE<9 -// Use getAttributeNode to fetch booleans when getAttribute lies -if ( !assert( function( el ) { - return el.getAttribute( "disabled" ) == null; -} ) ) { - addHandle( booleans, function( elem, name, isXML ) { - var val; - if ( !isXML ) { - return elem[ name ] === true ? name.toLowerCase() : - ( val = elem.getAttributeNode( name ) ) && val.specified ? - val.value : - null; - } - } ); -} - -return Sizzle; - -} )( window ); - - - -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; +jQuery.find = find; // Deprecated jQuery.expr[ ":" ] = jQuery.expr.pseudos; -jQuery.uniqueSort = jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; -jQuery.escapeSelector = Sizzle.escape; +jQuery.unique = jQuery.uniqueSort; +// These have always been private, but they used to be documented as part of +// Sizzle so let's maintain them for now for backwards compatibility purposes. +find.compile = compile; +find.select = select; +find.setDocument = setDocument; +find.tokenize = tokenize; +find.escape = jQuery.escapeSelector; +find.getText = jQuery.text; +find.isXML = jQuery.isXMLDoc; +find.selectors = jQuery.expr; +find.support = jQuery.support; +find.uniqueSort = jQuery.uniqueSort; + + /* eslint-enable */ + +} )(); var dir = function( elem, dir, until ) { @@ -3024,13 +2754,6 @@ var siblings = function( n, elem ) { var rneedsContext = jQuery.expr.match.needsContext; - - -function nodeName( elem, name ) { - - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - -} var rsingleTag = ( /^<([a-z][^\/\0>:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i ); @@ -3281,7 +3004,7 @@ jQuery.fn.extend( { if ( cur.nodeType < 11 && ( targets ? targets.index( cur ) > -1 : - // Don't pass non-elements to Sizzle + // Don't pass non-elements to jQuery#find cur.nodeType === 1 && jQuery.find.matchesSelector( cur, selectors ) ) ) { @@ -3836,7 +3559,7 @@ jQuery.extend( { if ( jQuery.Deferred.exceptionHook ) { jQuery.Deferred.exceptionHook( e, - process.stackTrace ); + process.error ); } // Support: Promises/A+ section 2.3.3.3.4.1 @@ -3864,10 +3587,17 @@ jQuery.extend( { process(); } else { - // Call an optional hook to record the stack, in case of exception + // Call an optional hook to record the error, in case of exception // since it's otherwise lost when execution goes async - if ( jQuery.Deferred.getStackHook ) { - process.stackTrace = jQuery.Deferred.getStackHook(); + if ( jQuery.Deferred.getErrorHook ) { + process.error = jQuery.Deferred.getErrorHook(); + + // The deprecated alias of the above. While the name suggests + // returning the stack, not an error instance, jQuery just passes + // it directly to `console.warn` so both will work; an instance + // just better cooperates with source maps. + } else if ( jQuery.Deferred.getStackHook ) { + process.error = jQuery.Deferred.getStackHook(); } window.setTimeout( process ); } @@ -4042,12 +3772,16 @@ jQuery.extend( { // warn about them ASAP rather than swallowing them by default. var rerrorNames = /^(Eval|Internal|Range|Reference|Syntax|Type|URI)Error$/; -jQuery.Deferred.exceptionHook = function( error, stack ) { +// If `jQuery.Deferred.getErrorHook` is defined, `asyncError` is an error +// captured before the async barrier to get the original error cause +// which may otherwise be hidden. +jQuery.Deferred.exceptionHook = function( error, asyncError ) { // Support: IE 8 - 9 only // Console exists when dev tools are open, which can happen at any time if ( window.console && window.console.warn && error && rerrorNames.test( error.name ) ) { - window.console.warn( "jQuery.Deferred exception: " + error.message, error.stack, stack ); + window.console.warn( "jQuery.Deferred exception: " + error.message, + error.stack, asyncError ); } }; @@ -5103,25 +4837,6 @@ function returnFalse() { return false; } -// Support: IE <=9 - 11+ -// focus() and blur() are asynchronous, except when they are no-op. -// So expect focus to be synchronous when the element is already active, -// and blur to be synchronous when the element is not already active. -// (focus and blur are always synchronous in other supported browsers, -// this just defines when we can count on it). -function expectSync( elem, type ) { - return ( elem === safeActiveElement() ) === ( type === "focus" ); -} - -// Support: IE <=9 only -// Accessing document.activeElement can throw unexpectedly -// https://bugs.jquery.com/ticket/13393 -function safeActiveElement() { - try { - return document.activeElement; - } catch ( err ) { } -} - function on( elem, types, selector, data, fn, one ) { var origFn, type; @@ -5559,7 +5274,7 @@ jQuery.event = { el.click && nodeName( el, "input" ) ) { // dataPriv.set( el, "click", ... ) - leverageNative( el, "click", returnTrue ); + leverageNative( el, "click", true ); } // Return false to allow normal processing in the caller @@ -5610,10 +5325,10 @@ jQuery.event = { // synthetic events by interrupting progress until reinvoked in response to // *native* events that it fires directly, ensuring that state changes have // already occurred before other listeners are invoked. -function leverageNative( el, type, expectSync ) { +function leverageNative( el, type, isSetup ) { - // Missing expectSync indicates a trigger call, which must force setup through jQuery.event.add - if ( !expectSync ) { + // Missing `isSetup` indicates a trigger call, which must force setup through jQuery.event.add + if ( !isSetup ) { if ( dataPriv.get( el, type ) === undefined ) { jQuery.event.add( el, type, returnTrue ); } @@ -5625,15 +5340,13 @@ function leverageNative( el, type, expectSync ) { jQuery.event.add( el, type, { namespace: false, handler: function( event ) { - var notAsync, result, + var result, saved = dataPriv.get( this, type ); if ( ( event.isTrigger & 1 ) && this[ type ] ) { // Interrupt processing of the outer synthetic .trigger()ed event - // Saved data should be false in such cases, but might be a leftover capture object - // from an async native handler (gh-4350) - if ( !saved.length ) { + if ( !saved ) { // Store arguments for use when handling the inner native event // There will always be at least one argument (an event object), so this array @@ -5642,33 +5355,22 @@ function leverageNative( el, type, expectSync ) { dataPriv.set( this, type, saved ); // Trigger the native event and capture its result - // Support: IE <=9 - 11+ - // focus() and blur() are asynchronous - notAsync = expectSync( this, type ); this[ type ](); result = dataPriv.get( this, type ); - if ( saved !== result || notAsync ) { - dataPriv.set( this, type, false ); - } else { - result = {}; - } + dataPriv.set( this, type, false ); + if ( saved !== result ) { // Cancel the outer synthetic event event.stopImmediatePropagation(); event.preventDefault(); - // Support: Chrome 86+ - // In Chrome, if an element having a focusout handler is blurred by - // clicking outside of it, it invokes the handler synchronously. If - // that handler calls `.remove()` on the element, the data is cleared, - // leaving `result` undefined. We need to guard against this. - return result && result.value; + return result; } // If this is an inner synthetic event for an event with a bubbling surrogate - // (focus or blur), assume that the surrogate already propagated from triggering the - // native event and prevent that from happening again here. + // (focus or blur), assume that the surrogate already propagated from triggering + // the native event and prevent that from happening again here. // This technically gets the ordering wrong w.r.t. to `.trigger()` (in which the // bubbling surrogate propagates *after* the non-bubbling base), but that seems // less bad than duplication. @@ -5678,22 +5380,25 @@ function leverageNative( el, type, expectSync ) { // If this is a native event triggered above, everything is now in order // Fire an inner synthetic event with the original arguments - } else if ( saved.length ) { + } else if ( saved ) { // ...and capture the result - dataPriv.set( this, type, { - value: jQuery.event.trigger( - - // Support: IE <=9 - 11+ - // Extend with the prototype to reset the above stopImmediatePropagation() - jQuery.extend( saved[ 0 ], jQuery.Event.prototype ), - saved.slice( 1 ), - this - ) - } ); - - // Abort handling of the native event - event.stopImmediatePropagation(); + dataPriv.set( this, type, jQuery.event.trigger( + saved[ 0 ], + saved.slice( 1 ), + this + ) ); + + // Abort handling of the native event by all jQuery handlers while allowing + // native handlers on the same element to run. On target, this is achieved + // by stopping immediate propagation just on the jQuery event. However, + // the native event is re-wrapped by a jQuery one on each level of the + // propagation so the only way to stop it for jQuery is to stop it for + // everyone via native `stopPropagation()`. This is not a problem for + // focus/blur which don't bubble, but it does also stop click on checkboxes + // and radios. We accept this limitation. + event.stopPropagation(); + event.isImmediatePropagationStopped = returnTrue; } } } ); @@ -5832,18 +5537,73 @@ jQuery.each( { }, jQuery.event.addProp ); jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateType ) { + + function focusMappedHandler( nativeEvent ) { + if ( document.documentMode ) { + + // Support: IE 11+ + // Attach a single focusin/focusout handler on the document while someone wants + // focus/blur. This is because the former are synchronous in IE while the latter + // are async. In other browsers, all those handlers are invoked synchronously. + + // `handle` from private data would already wrap the event, but we need + // to change the `type` here. + var handle = dataPriv.get( this, "handle" ), + event = jQuery.event.fix( nativeEvent ); + event.type = nativeEvent.type === "focusin" ? "focus" : "blur"; + event.isSimulated = true; + + // First, handle focusin/focusout + handle( nativeEvent ); + + // ...then, handle focus/blur + // + // focus/blur don't bubble while focusin/focusout do; simulate the former by only + // invoking the handler at the lower level. + if ( event.target === event.currentTarget ) { + + // The setup part calls `leverageNative`, which, in turn, calls + // `jQuery.event.add`, so event handle will already have been set + // by this point. + handle( event ); + } + } else { + + // For non-IE browsers, attach a single capturing handler on the document + // while someone wants focusin/focusout. + jQuery.event.simulate( delegateType, nativeEvent.target, + jQuery.event.fix( nativeEvent ) ); + } + } + jQuery.event.special[ type ] = { // Utilize native event if possible so blur/focus sequence is correct setup: function() { + var attaches; + // Claim the first handler // dataPriv.set( this, "focus", ... ) // dataPriv.set( this, "blur", ... ) - leverageNative( this, type, expectSync ); + leverageNative( this, type, true ); - // Return false to allow normal processing in the caller - return false; + if ( document.documentMode ) { + + // Support: IE 9 - 11+ + // We use the same native handler for focusin & focus (and focusout & blur) + // so we need to coordinate setup & teardown parts between those events. + // Use `delegateType` as the key as `type` is already used by `leverageNative`. + attaches = dataPriv.get( this, delegateType ); + if ( !attaches ) { + this.addEventListener( delegateType, focusMappedHandler ); + } + dataPriv.set( this, delegateType, ( attaches || 0 ) + 1 ); + } else { + + // Return false to allow normal processing in the caller + return false; + } }, trigger: function() { @@ -5854,6 +5614,24 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp return true; }, + teardown: function() { + var attaches; + + if ( document.documentMode ) { + attaches = dataPriv.get( this, delegateType ) - 1; + if ( !attaches ) { + this.removeEventListener( delegateType, focusMappedHandler ); + dataPriv.remove( this, delegateType ); + } else { + dataPriv.set( this, delegateType, attaches ); + } + } else { + + // Return false to indicate standard teardown should be applied + return false; + } + }, + // Suppress native focus or blur if we're currently inside // a leveraged native-event stack _default: function( event ) { @@ -5862,6 +5640,58 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp delegateType: delegateType }; + + // Support: Firefox <=44 + // Firefox doesn't have focus(in | out) events + // Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 + // + // Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 + // focus(in | out) events fire after focus & blur events, + // which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order + // Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 + // + // Support: IE 9 - 11+ + // To preserve relative focusin/focus & focusout/blur event order guaranteed on the 3.x branch, + // attach a single handler for both events in IE. + jQuery.event.special[ delegateType ] = { + setup: function() { + + // Handle: regular nodes (via `this.ownerDocument`), window + // (via `this.document`) & document (via `this`). + var doc = this.ownerDocument || this.document || this, + dataHolder = document.documentMode ? this : doc, + attaches = dataPriv.get( dataHolder, delegateType ); + + // Support: IE 9 - 11+ + // We use the same native handler for focusin & focus (and focusout & blur) + // so we need to coordinate setup & teardown parts between those events. + // Use `delegateType` as the key as `type` is already used by `leverageNative`. + if ( !attaches ) { + if ( document.documentMode ) { + this.addEventListener( delegateType, focusMappedHandler ); + } else { + doc.addEventListener( type, focusMappedHandler, true ); + } + } + dataPriv.set( dataHolder, delegateType, ( attaches || 0 ) + 1 ); + }, + teardown: function() { + var doc = this.ownerDocument || this.document || this, + dataHolder = document.documentMode ? this : doc, + attaches = dataPriv.get( dataHolder, delegateType ) - 1; + + if ( !attaches ) { + if ( document.documentMode ) { + this.removeEventListener( delegateType, focusMappedHandler ); + } else { + doc.removeEventListener( type, focusMappedHandler, true ); + } + dataPriv.remove( dataHolder, delegateType ); + } else { + dataPriv.set( dataHolder, delegateType, attaches ); + } + } + }; } ); // Create mouseenter/leave events using mouseover/out and event-time checks @@ -6093,7 +5923,7 @@ function domManip( collection, args, callback, ignored ) { if ( hasScripts ) { doc = scripts[ scripts.length - 1 ].ownerDocument; - // Reenable scripts + // Re-enable scripts jQuery.map( scripts, restoreScript ); // Evaluate executable scripts on first document insertion @@ -6164,7 +5994,8 @@ jQuery.extend( { if ( !support.noCloneChecked && ( elem.nodeType === 1 || elem.nodeType === 11 ) && !jQuery.isXMLDoc( elem ) ) { - // We eschew Sizzle here for performance reasons: https://jsperf.com/getall-vs-sizzle/2 + // We eschew jQuery#find here for performance reasons: + // https://jsperf.com/getall-vs-sizzle/2 destElements = getAll( clone ); srcElements = getAll( elem ); @@ -6440,15 +6271,6 @@ var swap = function( elem, options, callback ) { var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); -var whitespace = "[\\x20\\t\\r\\n\\f]"; - - -var rtrimCSS = new RegExp( - "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", - "g" -); - - ( function() { @@ -6558,7 +6380,7 @@ var rtrimCSS = new RegExp( trChild = document.createElement( "div" ); table.style.cssText = "position:absolute;left:-11111px;border-collapse:separate"; - tr.style.cssText = "border:1px solid"; + tr.style.cssText = "box-sizing:content-box;border:1px solid"; // Support: Chrome 86+ // Height set through cssText does not get applied. @@ -6570,7 +6392,7 @@ var rtrimCSS = new RegExp( // In our bodyBackground.html iframe, // display for all div elements is set to "inline", // which causes a problem only in Android 8 Chrome 86. - // Ensuring the div is display: block + // Ensuring the div is `display: block` // gets around this issue. trChild.style.display = "block"; @@ -6608,17 +6430,37 @@ function curCSS( elem, name, computed ) { // .css('filter') (IE 9 only, trac-12537) // .css('--customProperty) (gh-3144) if ( computed ) { - ret = computed.getPropertyValue( name ) || computed[ name ]; - // trim whitespace for custom property (issue gh-4926) - if ( isCustomProp ) { + // Support: IE <=9 - 11+ + // IE only supports `"float"` in `getPropertyValue`; in computed styles + // it's only available as `"cssFloat"`. We no longer modify properties + // sent to `.css()` apart from camelCasing, so we need to check both. + // Normally, this would create difference in behavior: if + // `getPropertyValue` returns an empty string, the value returned + // by `.css()` would be `undefined`. This is usually the case for + // disconnected elements. However, in IE even disconnected elements + // with no styles return `"none"` for `getPropertyValue( "float" )` + ret = computed.getPropertyValue( name ) || computed[ name ]; - // rtrim treats U+000D CARRIAGE RETURN and U+000C FORM FEED + if ( isCustomProp && ret ) { + + // Support: Firefox 105+, Chrome <=105+ + // Spec requires trimming whitespace for custom properties (gh-4926). + // Firefox only trims leading whitespace. Chrome just collapses + // both leading & trailing whitespace to a single space. + // + // Fall back to `undefined` if empty string returned. + // This collapses a missing definition with property defined + // and set to an empty string but there's no standard API + // allowing us to differentiate them without a performance penalty + // and returning `undefined` aligns with older jQuery. + // + // rtrimCSS treats U+000D CARRIAGE RETURN and U+000C FORM FEED // as whitespace while CSS does not, but this is not a problem // because CSS preprocessing replaces them with U+000A LINE FEED // (which *is* CSS whitespace) // https://www.w3.org/TR/css-syntax-3/#input-preprocessing - ret = ret.replace( rtrimCSS, "$1" ); + ret = ret.replace( rtrimCSS, "$1" ) || undefined; } if ( ret === "" && !isAttached( elem ) ) { @@ -6737,7 +6579,8 @@ function setPositiveNumber( _elem, value, subtract ) { function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computedVal ) { var i = dimension === "width" ? 1 : 0, extra = 0, - delta = 0; + delta = 0, + marginDelta = 0; // Adjustment may not be necessary if ( box === ( isBorderBox ? "border" : "content" ) ) { @@ -6747,8 +6590,10 @@ function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computed for ( ; i < 4; i += 2 ) { // Both box models exclude margin + // Count margin delta separately to only add it after scroll gutter adjustment. + // This is needed to make negative margins work with `outerHeight( true )` (gh-3982). if ( box === "margin" ) { - delta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); + marginDelta += jQuery.css( elem, box + cssExpand[ i ], true, styles ); } // If we get here with a content-box, we're seeking "padding" or "border" or "margin" @@ -6799,7 +6644,7 @@ function boxModelAdjustment( elem, dimension, box, isBorderBox, styles, computed ) ) || 0; } - return delta; + return delta + marginDelta; } function getWidthOrHeight( elem, dimension, extra ) { @@ -6897,26 +6742,35 @@ jQuery.extend( { // Don't automatically add "px" to these possibly-unitless properties cssNumber: { - "animationIterationCount": true, - "columnCount": true, - "fillOpacity": true, - "flexGrow": true, - "flexShrink": true, - "fontWeight": true, - "gridArea": true, - "gridColumn": true, - "gridColumnEnd": true, - "gridColumnStart": true, - "gridRow": true, - "gridRowEnd": true, - "gridRowStart": true, - "lineHeight": true, - "opacity": true, - "order": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true + animationIterationCount: true, + aspectRatio: true, + borderImageSlice: true, + columnCount: true, + flexGrow: true, + flexShrink: true, + fontWeight: true, + gridArea: true, + gridColumn: true, + gridColumnEnd: true, + gridColumnStart: true, + gridRow: true, + gridRowEnd: true, + gridRowStart: true, + lineHeight: true, + opacity: true, + order: true, + orphans: true, + scale: true, + widows: true, + zIndex: true, + zoom: true, + + // SVG-related + fillOpacity: true, + floodOpacity: true, + stopOpacity: true, + strokeMiterlimit: true, + strokeOpacity: true }, // Add in properties whose names you wish to fix before @@ -8642,9 +8496,39 @@ jQuery.each( [ "radio", "checkbox" ], function() { // Return jQuery for attributes-only inclusion +var location = window.location; + +var nonce = { guid: Date.now() }; +var rquery = ( /\?/ ); -support.focusin = "onfocusin" in window; + + +// Cross-browser xml parsing +jQuery.parseXML = function( data ) { + var xml, parserErrorElem; + if ( !data || typeof data !== "string" ) { + return null; + } + + // Support: IE 9 - 11 only + // IE throws on parseFromString with invalid input. + try { + xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); + } catch ( e ) {} + + parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; + if ( !xml || parserErrorElem ) { + jQuery.error( "Invalid XML: " + ( + parserErrorElem ? + jQuery.map( parserErrorElem.childNodes, function( el ) { + return el.textContent; + } ).join( "\n" ) : + data + ) ); + } + return xml; +}; var rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, @@ -8832,85 +8716,6 @@ jQuery.fn.extend( { } ); -// Support: Firefox <=44 -// Firefox doesn't have focus(in | out) events -// Related ticket - https://bugzilla.mozilla.org/show_bug.cgi?id=687787 -// -// Support: Chrome <=48 - 49, Safari <=9.0 - 9.1 -// focus(in | out) events fire after focus & blur events, -// which is spec violation - http://www.w3.org/TR/DOM-Level-3-Events/#events-focusevent-event-order -// Related ticket - https://bugs.chromium.org/p/chromium/issues/detail?id=449857 -if ( !support.focusin ) { - jQuery.each( { focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler on the document while someone wants focusin/focusout - var handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ) ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - - // Handle: regular nodes (via `this.ownerDocument`), window - // (via `this.document`) & document (via `this`). - var doc = this.ownerDocument || this.document || this, - attaches = dataPriv.access( doc, fix ); - - if ( !attaches ) { - doc.addEventListener( orig, handler, true ); - } - dataPriv.access( doc, fix, ( attaches || 0 ) + 1 ); - }, - teardown: function() { - var doc = this.ownerDocument || this.document || this, - attaches = dataPriv.access( doc, fix ) - 1; - - if ( !attaches ) { - doc.removeEventListener( orig, handler, true ); - dataPriv.remove( doc, fix ); - - } else { - dataPriv.access( doc, fix, attaches ); - } - } - }; - } ); -} -var location = window.location; - -var nonce = { guid: Date.now() }; - -var rquery = ( /\?/ ); - - - -// Cross-browser xml parsing -jQuery.parseXML = function( data ) { - var xml, parserErrorElem; - if ( !data || typeof data !== "string" ) { - return null; - } - - // Support: IE 9 - 11 only - // IE throws on parseFromString with invalid input. - try { - xml = ( new window.DOMParser() ).parseFromString( data, "text/xml" ); - } catch ( e ) {} - - parserErrorElem = xml && xml.getElementsByTagName( "parsererror" )[ 0 ]; - if ( !xml || parserErrorElem ) { - jQuery.error( "Invalid XML: " + ( - parserErrorElem ? - jQuery.map( parserErrorElem.childNodes, function( el ) { - return el.textContent; - } ).join( "\n" ) : - data - ) ); - } - return xml; -}; - - var rbracket = /\[\]$/, rCRLF = /\r?\n/g, @@ -10755,7 +10560,9 @@ jQuery.fn.extend( { }, hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); + return this + .on( "mouseenter", fnOver ) + .on( "mouseleave", fnOut || fnOver ); } } ); diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-3.7.1.min.js b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-3.7.1.min.js new file mode 100644 index 00000000000..7f37b5d9912 --- /dev/null +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/jquery/jquery-3.7.1.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.7.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(ie,e){"use strict";var oe=[],r=Object.getPrototypeOf,ae=oe.slice,g=oe.flat?function(e){return oe.flat.call(e)}:function(e){return oe.concat.apply([],e)},s=oe.push,se=oe.indexOf,n={},i=n.toString,ue=n.hasOwnProperty,o=ue.toString,a=o.call(Object),le={},v=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},y=function(e){return null!=e&&e===e.window},C=ie.document,u={type:!0,src:!0,nonce:!0,noModule:!0};function m(e,t,n){var r,i,o=(n=n||C).createElement("script");if(o.text=e,t)for(r in u)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function x(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[i.call(e)]||"object":typeof e}var t="3.7.1",l=/HTML$/i,ce=function(e,t){return new ce.fn.init(e,t)};function c(e){var t=!!e&&"length"in e&&e.length,n=x(e);return!v(e)&&!y(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+ge+")"+ge+"*"),x=new RegExp(ge+"|>"),j=new RegExp(g),A=new RegExp("^"+t+"$"),D={ID:new RegExp("^#("+t+")"),CLASS:new RegExp("^\\.("+t+")"),TAG:new RegExp("^("+t+"|[*])"),ATTR:new RegExp("^"+p),PSEUDO:new RegExp("^"+g),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+ge+"*(even|odd|(([+-]|)(\\d*)n|)"+ge+"*(?:([+-]|)"+ge+"*(\\d+)|))"+ge+"*\\)|)","i"),bool:new RegExp("^(?:"+f+")$","i"),needsContext:new RegExp("^"+ge+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+ge+"*((?:-\\d)?\\d*)"+ge+"*\\)|)(?=[^-]|$)","i")},N=/^(?:input|select|textarea|button)$/i,q=/^h\d$/i,L=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,H=/[+~]/,O=new RegExp("\\\\[\\da-fA-F]{1,6}"+ge+"?|\\\\([^\\r\\n\\f])","g"),P=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},M=function(){V()},R=J(function(e){return!0===e.disabled&&fe(e,"fieldset")},{dir:"parentNode",next:"legend"});try{k.apply(oe=ae.call(ye.childNodes),ye.childNodes),oe[ye.childNodes.length].nodeType}catch(e){k={apply:function(e,t){me.apply(e,ae.call(t))},call:function(e){me.apply(e,ae.call(arguments,1))}}}function I(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(V(e),e=e||T,C)){if(11!==p&&(u=L.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return k.call(n,a),n}else if(f&&(a=f.getElementById(i))&&I.contains(e,a)&&a.id===i)return k.call(n,a),n}else{if(u[2])return k.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&e.getElementsByClassName)return k.apply(n,e.getElementsByClassName(i)),n}if(!(h[t+" "]||d&&d.test(t))){if(c=t,f=e,1===p&&(x.test(t)||m.test(t))){(f=H.test(t)&&U(e.parentNode)||e)==e&&le.scope||((s=e.getAttribute("id"))?s=ce.escapeSelector(s):e.setAttribute("id",s=S)),o=(l=Y(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+Q(l[o]);c=l.join(",")}try{return k.apply(n,f.querySelectorAll(c)),n}catch(e){h(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return re(t.replace(ve,"$1"),e,n,r)}function W(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function F(e){return e[S]=!0,e}function $(e){var t=T.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function B(t){return function(e){return fe(e,"input")&&e.type===t}}function _(t){return function(e){return(fe(e,"input")||fe(e,"button"))&&e.type===t}}function z(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&R(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function X(a){return F(function(o){return o=+o,F(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function U(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}function V(e){var t,n=e?e.ownerDocument||e:ye;return n!=T&&9===n.nodeType&&n.documentElement&&(r=(T=n).documentElement,C=!ce.isXMLDoc(T),i=r.matches||r.webkitMatchesSelector||r.msMatchesSelector,r.msMatchesSelector&&ye!=T&&(t=T.defaultView)&&t.top!==t&&t.addEventListener("unload",M),le.getById=$(function(e){return r.appendChild(e).id=ce.expando,!T.getElementsByName||!T.getElementsByName(ce.expando).length}),le.disconnectedMatch=$(function(e){return i.call(e,"*")}),le.scope=$(function(){return T.querySelectorAll(":scope")}),le.cssHas=$(function(){try{return T.querySelector(":has(*,:jqfake)"),!1}catch(e){return!0}}),le.getById?(b.filter.ID=function(e){var t=e.replace(O,P);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(O,P);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&C){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):t.querySelectorAll(e)},b.find.CLASS=function(e,t){if("undefined"!=typeof t.getElementsByClassName&&C)return t.getElementsByClassName(e)},d=[],$(function(e){var t;r.appendChild(e).innerHTML="",e.querySelectorAll("[selected]").length||d.push("\\["+ge+"*(?:value|"+f+")"),e.querySelectorAll("[id~="+S+"-]").length||d.push("~="),e.querySelectorAll("a#"+S+"+*").length||d.push(".#.+[+~]"),e.querySelectorAll(":checked").length||d.push(":checked"),(t=T.createElement("input")).setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),r.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&d.push(":enabled",":disabled"),(t=T.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||d.push("\\["+ge+"*name"+ge+"*="+ge+"*(?:''|\"\")")}),le.cssHas||d.push(":has"),d=d.length&&new RegExp(d.join("|")),l=function(e,t){if(e===t)return a=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!le.sortDetached&&t.compareDocumentPosition(e)===n?e===T||e.ownerDocument==ye&&I.contains(ye,e)?-1:t===T||t.ownerDocument==ye&&I.contains(ye,t)?1:o?se.call(o,e)-se.call(o,t):0:4&n?-1:1)}),T}for(e in I.matches=function(e,t){return I(e,null,null,t)},I.matchesSelector=function(e,t){if(V(e),C&&!h[t+" "]&&(!d||!d.test(t)))try{var n=i.call(e,t);if(n||le.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){h(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(O,P),e[3]=(e[3]||e[4]||e[5]||"").replace(O,P),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||I.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&I.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return D.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&j.test(n)&&(t=Y(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(O,P).toLowerCase();return"*"===e?function(){return!0}:function(e){return fe(e,t)}},CLASS:function(e){var t=s[e+" "];return t||(t=new RegExp("(^|"+ge+")"+e+"("+ge+"|$)"))&&s(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=I.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function T(e,n,r){return v(n)?ce.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?ce.grep(e,function(e){return e===n!==r}):"string"!=typeof n?ce.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(ce.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||k,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:S.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof ce?t[0]:t,ce.merge(this,ce.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:C,!0)),w.test(r[1])&&ce.isPlainObject(t))for(r in t)v(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=C.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):v(e)?void 0!==n.ready?n.ready(e):e(ce):ce.makeArray(e,this)}).prototype=ce.fn,k=ce(C);var E=/^(?:parents|prev(?:Until|All))/,j={children:!0,contents:!0,next:!0,prev:!0};function A(e,t){while((e=e[t])&&1!==e.nodeType);return e}ce.fn.extend({has:function(e){var t=ce(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,Ce=/^$|^module$|\/(?:java|ecma)script/i;xe=C.createDocumentFragment().appendChild(C.createElement("div")),(be=C.createElement("input")).setAttribute("type","radio"),be.setAttribute("checked","checked"),be.setAttribute("name","t"),xe.appendChild(be),le.checkClone=xe.cloneNode(!0).cloneNode(!0).lastChild.checked,xe.innerHTML="",le.noCloneChecked=!!xe.cloneNode(!0).lastChild.defaultValue,xe.innerHTML="",le.option=!!xe.lastChild;var ke={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function Se(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&fe(e,t)?ce.merge([e],n):n}function Ee(e,t){for(var n=0,r=e.length;n",""]);var je=/<|&#?\w+;/;function Ae(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function Re(e,t){return fe(e,"table")&&fe(11!==t.nodeType?t:t.firstChild,"tr")&&ce(e).children("tbody")[0]||e}function Ie(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function We(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Fe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(_.hasData(e)&&(s=_.get(e).events))for(i in _.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),C.head.appendChild(r[0])},abort:function(){i&&i()}}});var Jt,Kt=[],Zt=/(=)\?(?=&|$)|\?\?/;ce.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Kt.pop()||ce.expando+"_"+jt.guid++;return this[e]=!0,e}}),ce.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Zt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Zt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=v(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Zt,"$1"+r):!1!==e.jsonp&&(e.url+=(At.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||ce.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=ie[r],ie[r]=function(){o=arguments},n.always(function(){void 0===i?ce(ie).removeProp(r):ie[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Kt.push(r)),o&&v(i)&&i(o[0]),o=i=void 0}),"script"}),le.createHTMLDocument=((Jt=C.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Jt.childNodes.length),ce.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(le.createHTMLDocument?((r=(t=C.implementation.createHTMLDocument("")).createElement("base")).href=C.location.href,t.head.appendChild(r)):t=C),o=!n&&[],(i=w.exec(e))?[t.createElement(i[1])]:(i=Ae([e],t,o),o&&o.length&&ce(o).remove(),ce.merge([],i.childNodes)));var r,i,o},ce.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(ce.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},ce.expr.pseudos.animated=function(t){return ce.grep(ce.timers,function(e){return t===e.elem}).length},ce.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=ce.css(e,"position"),c=ce(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=ce.css(e,"top"),u=ce.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),v(t)&&(t=t.call(e,n,ce.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},ce.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){ce.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===ce.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===ce.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=ce(e).offset()).top+=ce.css(e,"borderTopWidth",!0),i.left+=ce.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-ce.css(r,"marginTop",!0),left:t.left-i.left-ce.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===ce.css(e,"position"))e=e.offsetParent;return e||J})}}),ce.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;ce.fn[t]=function(e){return M(this,function(e,t,n){var r;if(y(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),ce.each(["top","left"],function(e,n){ce.cssHooks[n]=Ye(le.pixelPosition,function(e,t){if(t)return t=Ge(e,n),_e.test(t)?ce(e).position()[n]+"px":t})}),ce.each({Height:"height",Width:"width"},function(a,s){ce.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){ce.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return M(this,function(e,t,n){var r;return y(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?ce.css(e,t,i):ce.style(e,t,n,i)},s,n?e:void 0,n)}})}),ce.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){ce.fn[t]=function(e){return this.on(t,e)}}),ce.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.on("mouseenter",e).on("mouseleave",t||e)}}),ce.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){ce.fn[n]=function(e,t){return 0 rq = new ReferenceQueue(); @@ -58,6 +54,7 @@ protected void finalize() throws Throwable { public static void main(String[] args) throws InterruptedException { + Cleaner.create().register(str, () -> System.out.println("The Object is being finalized")); Thread reader = new Thread() { public void run() { while (wr.get() != null) { diff --git a/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWait.java b/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWait.java index 39031a6f55a..66cf04fd62f 100644 --- a/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWait.java +++ b/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWait.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright 2016 Azul Systems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -27,8 +27,10 @@ * @summary (x86 only) checks that java.lang.Thread.onSpinWait is intrinsified * @bug 8147844 * @library /test/lib - * @modules java.base/jdk.internal.misc + * + * @requires vm.flagless * @requires os.arch=="x86" | os.arch=="amd64" | os.arch=="x86_64" + * * @run driver compiler.onSpinWait.TestOnSpinWait */ diff --git a/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitC1.java b/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitC1.java index dff766ad1cc..fde38cf858e 100644 --- a/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitC1.java +++ b/test/hotspot/jtreg/compiler/onSpinWait/TestOnSpinWaitC1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. * Copyright 2016 Azul Systems, Inc. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -27,9 +27,11 @@ * @summary (x86 only) checks that java.lang.Thread.onSpinWait is intrinsified * @bug 8147844 * @library /test/lib - * @modules java.base/jdk.internal.misc + * + * @requires vm.flagless * @requires os.arch=="x86" | os.arch=="amd64" | os.arch=="x86_64" * @requires vm.compiler1.enabled + * * @run driver compiler.onSpinWait.TestOnSpinWaitC1 */ diff --git a/test/hotspot/jtreg/compiler/oracle/CheckCompileCommandOption.java b/test/hotspot/jtreg/compiler/oracle/CheckCompileCommandOption.java index 39aaf59daf2..ea15968895c 100644 --- a/test/hotspot/jtreg/compiler/oracle/CheckCompileCommandOption.java +++ b/test/hotspot/jtreg/compiler/oracle/CheckCompileCommandOption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, 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 @@ -28,6 +28,7 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management + * @requires vm.flagless * @run driver compiler.oracle.CheckCompileCommandOption */ diff --git a/test/hotspot/jtreg/compiler/oracle/TestCompileCommand.java b/test/hotspot/jtreg/compiler/oracle/TestCompileCommand.java index 458a2f452c2..0279843b590 100644 --- a/test/hotspot/jtreg/compiler/oracle/TestCompileCommand.java +++ b/test/hotspot/jtreg/compiler/oracle/TestCompileCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2021, 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 @@ -28,6 +28,7 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management + * @requires vm.flagless * @run driver compiler.oracle.TestCompileCommand */ diff --git a/test/hotspot/jtreg/compiler/runtime/Test8168712.java b/test/hotspot/jtreg/compiler/runtime/Test8168712.java index 00cffa3e757..14a46efc03a 100644 --- a/test/hotspot/jtreg/compiler/runtime/Test8168712.java +++ b/test/hotspot/jtreg/compiler/runtime/Test8168712.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2023, 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,20 +30,31 @@ */ package compiler.runtime; +import java.lang.ref.Cleaner; import java.util.*; public class Test8168712 { static HashSet m = new HashSet<>(); + + // One cleaner thread for cleaning all the instances. Otherwise, we get OOME. + static Cleaner cleaner = Cleaner.create(); + + public Test8168712() { + cleaner.register(this, () -> cleanup()); + } + public static void main(String args[]) { int i = 0; while (i++<15000) { test(); } } + static Test8168712 test() { return new Test8168712(); } - protected void finalize() { + + public void cleanup() { m.add(this); } } diff --git a/test/hotspot/jtreg/compiler/startup/NumCompilerThreadsCheck.java b/test/hotspot/jtreg/compiler/startup/NumCompilerThreadsCheck.java index 7f74264f941..9761002c051 100644 --- a/test/hotspot/jtreg/compiler/startup/NumCompilerThreadsCheck.java +++ b/test/hotspot/jtreg/compiler/startup/NumCompilerThreadsCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2021, 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,6 +26,7 @@ * @bug 8034775 * @summary Ensures correct minimal number of compiler threads (provided by -XX:CICompilerCount=) * @library /test/lib + * @requires vm.flagless * @modules java.base/jdk.internal.misc * java.management * diff --git a/test/hotspot/jtreg/compiler/startup/SmallCodeCacheStartup.java b/test/hotspot/jtreg/compiler/startup/SmallCodeCacheStartup.java index 8e2e6a1d663..b32c4d48f8a 100644 --- a/test/hotspot/jtreg/compiler/startup/SmallCodeCacheStartup.java +++ b/test/hotspot/jtreg/compiler/startup/SmallCodeCacheStartup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, 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 @@ -28,6 +28,7 @@ * to initialize all compiler threads. The option -Xcomp gives the VM more time to * trigger the old bug. * @library /test/lib + * @requires vm.flagless * @modules java.base/jdk.internal.misc * java.management * diff --git a/test/hotspot/jtreg/compiler/startup/StartupOutput.java b/test/hotspot/jtreg/compiler/startup/StartupOutput.java index f299c65abf2..0f9ab3b1f96 100644 --- a/test/hotspot/jtreg/compiler/startup/StartupOutput.java +++ b/test/hotspot/jtreg/compiler/startup/StartupOutput.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2021, 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,6 +26,7 @@ * @bug 8026949 8164091 * @summary Test ensures correct VM output during startup * @library /test/lib + * @requires vm.flagless * @modules java.base/jdk.internal.misc * java.management * diff --git a/test/hotspot/jtreg/containers/docker/EventGeneratorLoop.java b/test/hotspot/jtreg/containers/docker/EventGeneratorLoop.java new file mode 100644 index 00000000000..6354d80d31c --- /dev/null +++ b/test/hotspot/jtreg/containers/docker/EventGeneratorLoop.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +import jdk.jfr.Event; +import jdk.jfr.Description; +import jdk.jfr.Label; + + +// This class generates simple event in a loop +// for a specified time. +// Pass the time in seconds as a parameter. +public class EventGeneratorLoop { + + @Label("SimpleEvent") + @Description("Simple custom event") + static class SimpleEvent extends Event { + @Label("Message") + String msg; + + @Label("Count") + int count; + } + + + public static void main(String[] args) throws Exception { + if ((args.length < 1) || (args[0] == null)) { + throw new IllegalArgumentException("Expecting one argument: time to run (seconds)"); + } + int howLong = Integer.parseInt(args[0]); + + for (int i=0; i < howLong; i++) { + SimpleEvent ev = new SimpleEvent(); + ev.msg = "Hello"; + ev.count = i; + ev.commit(); + + try { Thread.sleep(1000); } catch (InterruptedException e) {} + System.out.print("."); + } + } +} diff --git a/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java new file mode 100644 index 00000000000..710f321350e --- /dev/null +++ b/test/hotspot/jtreg/containers/docker/TestJcmdWithSideCar.java @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + + +/* + * @test + * @summary Test JCMD with side car pattern. + * Sidecar is a common pattern used in the cloud environments for monitoring + * and other uses. In side car pattern the main application/service container + * is paired with a sidecar container by sharing certain aspects of container + * namespace such as PID namespace, specific sub-directories, IPC and more. + * @requires docker.support + * @library /test/lib + * @modules java.base/jdk.internal.misc + * java.management + * jdk.jartool/sun.tools.jar + * @build EventGeneratorLoop + * @run driver TestJcmdWithSideCar + */ +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Arrays; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; +import jdk.test.lib.Container; +import jdk.test.lib.Utils; +import jdk.test.lib.containers.docker.Common; +import jdk.test.lib.containers.docker.DockerRunOptions; +import jdk.test.lib.containers.docker.DockerTestUtils; +import jdk.test.lib.process.OutputAnalyzer; + + +public class TestJcmdWithSideCar { + private static final String IMAGE_NAME = Common.imageName("jfr-jcmd"); + private static final int TIME_TO_RUN_MAIN_PROCESS = (int) (30 * Utils.TIMEOUT_FACTOR); // seconds + private static final String MAIN_CONTAINER_NAME = "test-container-main"; + + public static void main(String[] args) throws Exception { + if (!DockerTestUtils.canTestDocker()) { + return; + } + + DockerTestUtils.buildJdkContainerImage(IMAGE_NAME); + + try { + // Start the loop process in the "main" container, then run test cases + // using a sidecar container. + DockerThread t = startMainContainer(); + + waitForMainContainerToStart(500, 10); + t.checkForErrors(); + + OutputAnalyzer jcmdOut = testCase01(); + long mainProcPid = findProcess(jcmdOut, "EventGeneratorLoop"); + + t.assertIsAlive(); + testCase02(mainProcPid); + + // JCMD does not work in sidecar configuration, except for "jcmd -l". + // Including this test case to assist in reproduction of the problem. + // t.assertIsAlive(); + // testCase03(mainProcPid); + + t.join(TIME_TO_RUN_MAIN_PROCESS * 1000); + t.checkForErrors(); + } finally { + DockerTestUtils.removeDockerImage(IMAGE_NAME); + } + } + + + // Run "jcmd -l" in a sidecar container and find a process that runs EventGeneratorLoop + private static OutputAnalyzer testCase01() throws Exception { + return runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jcmd", "-l") + .shouldHaveExitValue(0) + .shouldContain("sun.tools.jcmd.JCmd") + .shouldContain("EventGeneratorLoop"); + } + + // run jhsdb jinfo (jhsdb uses PTRACE) + private static void testCase02(long pid) throws Exception { + runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jhsdb", "jinfo", "--pid", "" + pid) + .shouldHaveExitValue(0) + .shouldContain("Java System Properties") + .shouldContain("VM Flags"); + } + + // test jcmd with some commands (help, start JFR recording) + // JCMD will use signal mechanism and Unix Socket + private static void testCase03(long pid) throws Exception { + runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jcmd", "" + pid, "help") + .shouldHaveExitValue(0) + .shouldContain("VM.version"); + runSideCar(MAIN_CONTAINER_NAME, "/jdk/bin/jcmd", "" + pid, "JFR.start") + .shouldHaveExitValue(0) + .shouldContain("Started recording"); + } + + private static DockerThread startMainContainer() throws Exception { + // start "main" container (the observee) + DockerRunOptions opts = commonDockerOpts("EventGeneratorLoop"); + opts.addDockerOpts("--cap-add=SYS_PTRACE") + .addDockerOpts("--name", MAIN_CONTAINER_NAME) + .addDockerOpts("-v", "/tmp") + .addJavaOpts("-XX:+UsePerfData") + .addClassOptions("" + TIME_TO_RUN_MAIN_PROCESS); + DockerThread t = new DockerThread(opts); + t.start(); + + return t; + } + + private static void waitForMainContainerToStart(int delayMillis, int count) throws Exception { + boolean started = false; + for(int i=0; i < count; i++) { + try { + Thread.sleep(delayMillis); + } catch (InterruptedException e) {} + if (isMainContainerRunning()) { + started = true; + break; + } + } + if (!started) { + throw new RuntimeException("Main container did not start"); + } + } + + private static boolean isMainContainerRunning() throws Exception { + OutputAnalyzer out = + DockerTestUtils.execute(Container.ENGINE_COMMAND, + "ps", "--no-trunc", + "--filter", "name=" + MAIN_CONTAINER_NAME); + return out.getStdout().contains(MAIN_CONTAINER_NAME); + } + + // JCMD relies on the attach mechanism (com.sun.tools.attach), + // which in turn relies on JVMSTAT mechanism, which puts its mapped + // buffers in /tmp directory (hsperfdata_). Thus, in sidecar + // we mount /tmp via --volumes-from from the main container. + private static OutputAnalyzer runSideCar(String MAIN_CONTAINER_NAME, String whatToRun, + String... args) throws Exception { + List cmd = new ArrayList<>(); + String[] command = new String[] { + Container.ENGINE_COMMAND, "run", + "--tty=true", "--rm", + "--cap-add=SYS_PTRACE", "--sig-proxy=true", + "--pid=container:" + MAIN_CONTAINER_NAME, + "--volumes-from", MAIN_CONTAINER_NAME, + IMAGE_NAME, whatToRun + }; + + cmd.addAll(Arrays.asList(command)); + cmd.addAll(Arrays.asList(args)); + return DockerTestUtils.execute(cmd); + } + + private static long findProcess(OutputAnalyzer out, String name) throws Exception { + List l = out.asLines() + .stream() + .filter(s -> s.contains(name)) + .collect(Collectors.toList()); + if (l.isEmpty()) { + throw new RuntimeException("Could not find matching process"); + } + String psInfo = l.get(0); + System.out.println("findProcess(): psInfo: " + psInfo); + String pid = psInfo.substring(0, psInfo.indexOf(' ')); + System.out.println("findProcess(): pid: " + pid); + return Long.parseLong(pid); + } + + private static DockerRunOptions commonDockerOpts(String className) { + return new DockerRunOptions(IMAGE_NAME, "/jdk/bin/java", className) + .addDockerOpts("--volume", Utils.TEST_CLASSES + ":/test-classes/") + .addJavaOpts("-cp", "/test-classes/"); + } + + + static class DockerThread extends Thread { + DockerRunOptions runOpts; + Exception exception; + + DockerThread(DockerRunOptions opts) { + runOpts = opts; + } + + public void run() { + try { + DockerTestUtils.dockerRunJava(runOpts); + } catch (Exception e) { + exception = e; + } + } + + public void assertIsAlive() throws Exception { + if (!isAlive()) { + throw new RuntimeException("DockerThread stopped unexpectedly"); + } + } + + public void checkForErrors() throws Exception { + if (exception != null) { + throw new RuntimeException("DockerThread threw exception" + + exception.getMessage()); + } + } + } + +} diff --git a/test/hotspot/jtreg/gc/arguments/TestDisableDefaultGC.java b/test/hotspot/jtreg/gc/arguments/TestDisableDefaultGC.java index 410c8f52596..c69400ff221 100644 --- a/test/hotspot/jtreg/gc/arguments/TestDisableDefaultGC.java +++ b/test/hotspot/jtreg/gc/arguments/TestDisableDefaultGC.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, 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 @@ -42,12 +42,13 @@ public class TestDisableDefaultGC { public static void main(String[] args) throws Exception { // Start VM, disabling all possible default GCs - ProcessBuilder pb = GCArguments.createJavaProcessBuilder("-XX:-UseSerialGC", - "-XX:-UseParallelGC", - "-XX:-UseG1GC", - "-XX:-UseConcMarkSweepGC", - "-XX:-UseZGC", - "-version"); + ProcessBuilder pb = GCArguments.createTestJvm("-XX:-UseSerialGC", + "-XX:-UseParallelGC", + "-XX:-UseG1GC", + "-XX:-UseConcMarkSweepGC", + "-XX:+UnlockExperimentalVMOptions", + "-XX:-UseZGC", + "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldMatch("Garbage collector not selected"); output.shouldHaveExitValue(1); diff --git a/test/hotspot/jtreg/gc/arguments/TestG1HeapSizeFlags.java b/test/hotspot/jtreg/gc/arguments/TestG1HeapSizeFlags.java index 78fda5d9bcc..60d1c16c0fa 100644 --- a/test/hotspot/jtreg/gc/arguments/TestG1HeapSizeFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestG1HeapSizeFlags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, 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,10 +25,10 @@ /* * @test TestG1HeapSizeFlags - * @key gc * @bug 8006088 - * @requires vm.gc.G1 * @summary Tests argument processing for initial and maximum heap size for the G1 collector + * @key gc flag-sensitive + * @requires vm.gc.G1 & vm.opt.x.Xmx == null & vm.opt.x.Xms == null & vm.opt.MinHeapSize == null & vm.opt.MaxHeapSize == null & vm.opt.InitialHeapSize == null * @library /test/lib * @library / * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/gc/arguments/TestG1PercentageOptions.java b/test/hotspot/jtreg/gc/arguments/TestG1PercentageOptions.java index edaa8c286bf..5a50b59c49c 100644 --- a/test/hotspot/jtreg/gc/arguments/TestG1PercentageOptions.java +++ b/test/hotspot/jtreg/gc/arguments/TestG1PercentageOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, 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,7 +27,7 @@ * @test TestG1PercentageOptions * @key gc * @bug 8068942 - * @requires vm.gc.G1 + * @requires vm.gc.G1 & vm.opt.G1ConfidencePercent == null * @summary Test argument processing of various percentage options * @library /test/lib * @library / @@ -65,8 +65,7 @@ private static final class OptionDescription { }; private static void check(String flag, boolean is_valid) throws Exception { - ProcessBuilder pb = GCArguments.createJavaProcessBuilder( - "-XX:+UseG1GC", flag, "-version"); + ProcessBuilder pb = GCArguments.createTestJvm("-XX:+UseG1GC", flag, "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); if (is_valid) { output.shouldHaveExitValue(0); @@ -75,8 +74,7 @@ private static void check(String flag, boolean is_valid) throws Exception { } } - private static - void check(String name, String value, boolean is_valid) throws Exception { + private static void check(String name, String value, boolean is_valid) throws Exception { check("-XX:" + name + "=" + value, is_valid); } diff --git a/test/hotspot/jtreg/gc/arguments/TestHeapFreeRatio.java b/test/hotspot/jtreg/gc/arguments/TestHeapFreeRatio.java index ad33f5b7a7f..137172509ba 100644 --- a/test/hotspot/jtreg/gc/arguments/TestHeapFreeRatio.java +++ b/test/hotspot/jtreg/gc/arguments/TestHeapFreeRatio.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, 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 @@ -28,6 +28,7 @@ * @key gc * @bug 8025661 * @summary Test parsing of -Xminf and -Xmaxf + * @requires vm.opt.x.Xminf == null & vm.opt.x.Xmaxf == null & vm.opt.MinHeapFreeRatio == null & vm.opt.MaxHeapFreeRatio == null * @library /test/lib * @library / * @modules java.base/jdk.internal.misc @@ -49,7 +50,7 @@ enum Validation { } private static void testMinMaxFreeRatio(String min, String max, Validation type) throws Exception { - ProcessBuilder pb = GCArguments.createJavaProcessBuilder( + ProcessBuilder pb = GCArguments.createTestJvm( "-Xminf" + min, "-Xmaxf" + max, "-version"); diff --git a/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java b/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java index bec4716efb1..a5e0b9c58be 100644 --- a/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java +++ b/test/hotspot/jtreg/gc/arguments/TestMaxHeapSizeTools.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, 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,10 +23,10 @@ package gc.arguments; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import java.util.ArrayList; import java.util.Arrays; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.process.OutputAnalyzer; @@ -70,26 +70,26 @@ public static void checkMinInitialErgonomics(String gcflag) throws Exception { long maxHeapSize = largeValue + (2 * 1024 * 1024); // -Xms is not set - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=0" }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize }, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + smallValue }, -1, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=" + largeValue }, -1, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-XX:InitialHeapSize=0" }, -1, -1); // -Xms is set to zero - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0" }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + smallValue }, values, -1, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + largeValue }, values, -1, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=0" }, values, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0" }, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + smallValue }, -1, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=" + largeValue }, -1, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms0", "-XX:InitialHeapSize=0" }, -1, -1); // -Xms is set to small value - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue }, values, -1, -1); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, values, smallValue, smallValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, values, smallValue, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, values, smallValue, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue }, -1, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + smallValue }, smallValue, smallValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=" + largeValue }, smallValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + smallValue, "-XX:InitialHeapSize=0" }, smallValue, -1); // -Xms is set to large value - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue }, values, largeValue, largeValue); - checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, values, largeValue, -1); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue }, largeValue, largeValue); + checkErgonomics(new String[] { gcflag, "-Xmx" + maxHeapSize, "-Xms" + largeValue, "-XX:InitialHeapSize=0" }, largeValue, -1); } private static long align_up(long value, long alignment) { @@ -98,7 +98,7 @@ private static long align_up(long value, long alignment) { } private static void getNewOldSize(String gcflag, long[] values) throws Exception { - ProcessBuilder pb = GCArguments.createJavaProcessBuilder(gcflag, + ProcessBuilder pb = GCArguments.createTestJvm(gcflag, "-XX:+PrintFlagsFinal", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); @@ -168,7 +168,7 @@ public static OutputAnalyzer runWhiteBoxTest(String[] vmargs, String classname, finalargs.add(classname); finalargs.addAll(Arrays.asList(arguments)); - ProcessBuilder pb = GCArguments.createJavaProcessBuilder(finalargs.toArray(String[]::new)); + ProcessBuilder pb = GCArguments.createTestJvm(finalargs.toArray(String[]::new)); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); @@ -206,7 +206,7 @@ private static void getMinInitialMaxHeap(String[] args, MinInitialMaxValues val) * Verify whether the VM automatically synchronizes minimum and initial heap size if only * one is given for the GC specified. */ - public static void checkErgonomics(String[] args, long[] newoldsize, + public static void checkErgonomics(String[] args, long expectedMin, long expectedInitial) throws Exception { MinInitialMaxValues v = new MinInitialMaxValues(); @@ -268,7 +268,7 @@ private static void shouldContainOrNot(OutputAnalyzer output, boolean contains, } private static void expect(String[] flags, boolean hasWarning, boolean hasError, int errorcode) throws Exception { - ProcessBuilder pb = GCArguments.createJavaProcessBuilder(flags); + ProcessBuilder pb = GCArguments.createTestJvm(flags); OutputAnalyzer output = new OutputAnalyzer(pb.start()); shouldContainOrNot(output, hasWarning, "Warning"); shouldContainOrNot(output, hasError, "Error"); diff --git a/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java b/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java index 7c10e1e27a2..cdfd0e829f8 100644 --- a/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java +++ b/test/hotspot/jtreg/gc/arguments/TestMaxNewSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, 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 @@ -29,7 +29,8 @@ * @bug 7057939 * @summary Make sure that MaxNewSize always has a useful value after argument * processing. - * @requires vm.gc.Serial + * @key flag-sensitive + * @requires vm.gc.Serial & vm.opt.MaxNewSize == null & vm.opt.NewRatio == null & vm.opt.NewSize == null & vm.opt.OldSize == null & vm.opt.x.Xms == null & vm.opt.x.Xmx == null * @library /test/lib * @library / * @modules java.base/jdk.internal.misc @@ -44,7 +45,8 @@ * @bug 7057939 * @summary Make sure that MaxNewSize always has a useful value after argument * processing. - * @requires vm.gc.Parallel + * @key flag-sensitive + * @requires vm.gc.Parallel & vm.opt.MaxNewSize == null & vm.opt.NewRatio == null & vm.opt.NewSize == null & vm.opt.OldSize == null & vm.opt.x.Xms == null & vm.opt.x.Xmx == null * @library /test/lib * @library / * @modules java.base/jdk.internal.misc @@ -59,7 +61,8 @@ * @bug 7057939 * @summary Make sure that MaxNewSize always has a useful value after argument * processing. - * @requires vm.gc.G1 + * @key flag-sensitive + * @requires vm.gc.G1 & vm.opt.MaxNewSize == null & vm.opt.NewRatio == null & vm.opt.NewSize == null & vm.opt.OldSize == null & vm.opt.x.Xms == null & vm.opt.x.Xmx == null * @library /test/lib * @library / * @modules java.base/jdk.internal.misc @@ -96,46 +99,23 @@ public class TestMaxNewSize { private static void checkMaxNewSize(String[] flags, int heapsize) throws Exception { BigInteger actual = new BigInteger(getMaxNewSize(flags)); - System.out.println(actual); - if (actual.compareTo(new BigInteger((new Long(heapsize)).toString())) == 1) { + System.out.println("asserting: " + actual + " <= " + heapsize); + if (actual.compareTo(new BigInteger("" + heapsize)) > 0) { throw new RuntimeException("MaxNewSize value set to \"" + actual + "\", expected otherwise when running with the following flags: " + Arrays.asList(flags).toString()); } } - private static void checkIncompatibleNewSize(String[] flags) throws Exception { - ArrayList finalargs = new ArrayList(); - finalargs.addAll(Arrays.asList(flags)); - finalargs.add("-version"); - - ProcessBuilder pb = GCArguments.createJavaProcessBuilder(finalargs); - OutputAnalyzer output = new OutputAnalyzer(pb.start()); - output.shouldContain("Initial young gen size set larger than the maximum young gen size"); - } - - private static boolean isRunningG1(String[] args) { - for (int i = 0; i < args.length; i++) { - if (args[i].contains("+UseG1GC")) { - return true; - } - } - return false; - } - private static String getMaxNewSize(String[] flags) throws Exception { ArrayList finalargs = new ArrayList(); finalargs.addAll(Arrays.asList(flags)); - if (isRunningG1(flags)) { - finalargs.add("-XX:G1HeapRegionSize=1M"); - } finalargs.add("-XX:+PrintFlagsFinal"); finalargs.add("-version"); - ProcessBuilder pb = GCArguments.createJavaProcessBuilder(finalargs); + ProcessBuilder pb = GCArguments.createTestJvm(finalargs); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldHaveExitValue(0); String stdout = output.getStdout(); - //System.out.println(stdout); return getFlagValue("MaxNewSize", stdout); } diff --git a/test/hotspot/jtreg/gc/arguments/TestParallelHeapSizeFlags.java b/test/hotspot/jtreg/gc/arguments/TestParallelHeapSizeFlags.java index 457e0396e00..092a291a58f 100644 --- a/test/hotspot/jtreg/gc/arguments/TestParallelHeapSizeFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestParallelHeapSizeFlags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, 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,11 +25,11 @@ /* * @test TestParallelHeapSizeFlags - * @key gc * @bug 8006088 * @summary Tests argument processing for initial and maximum heap size for the * parallel collectors. - * @requires vm.gc.Parallel + * @key gc flag-sensitive + * @requires vm.gc.Parallel & vm.opt.x.Xmx == null & vm.opt.x.Xms == null & vm.opt.MinHeapSize == null & vm.opt.MaxHeapSize == null & vm.opt.InitialHeapSize == null * @library /test/lib * @library / * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/gc/arguments/TestSerialHeapSizeFlags.java b/test/hotspot/jtreg/gc/arguments/TestSerialHeapSizeFlags.java index cab7229eb7f..7acf74dd873 100644 --- a/test/hotspot/jtreg/gc/arguments/TestSerialHeapSizeFlags.java +++ b/test/hotspot/jtreg/gc/arguments/TestSerialHeapSizeFlags.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, 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,9 +25,10 @@ /* * @test TestSerialHeapSizeFlags - * @key gc * @bug 8006088 * @summary Tests argument processing for initial and maximum heap size for the Serial collector + * @key gc flag-sensitive + * @requires vm.gc.Serial & vm.opt.x.Xmx == null & vm.opt.x.Xms == null & vm.opt.MinHeapSize == null & vm.opt.MaxHeapSize == null & vm.opt.InitialHeapSize == null * @library /test/lib * @library / * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/gc/g1/mixedgc/TestOldGenCollectionUsage.java b/test/hotspot/jtreg/gc/g1/mixedgc/TestOldGenCollectionUsage.java index 40b041d9a9c..06ef29fc454 100644 --- a/test/hotspot/jtreg/gc/g1/mixedgc/TestOldGenCollectionUsage.java +++ b/test/hotspot/jtreg/gc/g1/mixedgc/TestOldGenCollectionUsage.java @@ -136,8 +136,8 @@ public void run() { if (newCollectionCount <= collectionCount) { throw new RuntimeException("No new collection"); } - if (newCollectionTime <= collectionTime) { - throw new RuntimeException("Collector has not run some more"); + if (newCollectionTime < collectionTime) { + throw new RuntimeException("Collection time ran backwards"); } System.out.println("Test passed."); diff --git a/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java b/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java index 6e3fd239abe..ca3dc27ddab 100644 --- a/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java +++ b/test/hotspot/jtreg/serviceability/dcmd/framework/TestProcessLauncher.java @@ -50,7 +50,7 @@ public TestProcessLauncher(String className, ArgumentHandler argHandler) { } public TestProcessLauncher(String className) { - this(className, new ArgumentHandler(new String[0])); + this(className, new ArgumentHandler(new String[] {"-transport.address=dynamic"})); } public Process launch() { diff --git a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java index e188bddaaf3..642c6679ca8 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java +++ b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSize.java @@ -93,7 +93,7 @@ private static void startMeWithArgs() throws Exception { try { List vmArgs = new ArrayList(); vmArgs.add("-XX:+UsePerfData"); - vmArgs.addAll(Utils.getVmOptions()); + vmArgs.addAll(Arrays.asList(Utils.getTestJavaOpts())); app = LingeredApp.startApp(vmArgs); System.out.println ("Started LingeredApp with pid " + app.getPid()); } catch (Exception ex) { diff --git a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java index 231da097590..d5ac5ca87cf 100644 --- a/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java +++ b/test/hotspot/jtreg/serviceability/sa/TestInstanceKlassSizeForInterface.java @@ -22,6 +22,7 @@ */ import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import sun.jvm.hotspot.HotSpotAgent; @@ -154,9 +155,7 @@ public static void main (String... args) throws Exception { if (args == null || args.length == 0) { try { - List vmArgs = new ArrayList(); - vmArgs.addAll(Utils.getVmOptions()); - + List vmArgs = Arrays.asList(Utils.getTestJavaOpts()); theApp = new LingeredAppWithInterface(); LingeredApp.startApp(vmArgs, theApp); createAnotherToAttach(instanceKlassNames, diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large001/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large001/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large001/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large002/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large002/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large002/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large003/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large003/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large003/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large004/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large004/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large004/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large005/TEST.properties b/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large005/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/gc/gctests/LargeObjects/large005/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_0_1/TestDescription.java b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_0_1/TestDescription.java index f9e157b20ac..ce2fb6cf53c 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_0_1/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_0_1/TestDescription.java @@ -34,6 +34,7 @@ * @requires vm.gc != "G1" | !vm.opt.final.ClassUnloadingWithConcurrentMark * @requires vm.gc != "ConcMarkSweep" * @requires vm.gc != "Z" + * @requires vm.compMode != "Xcomp" * @library /vmTestbase /test/lib * @run driver jdk.test.lib.FileInstaller . . * @run main/othervm diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_10_20/TestDescription.java b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_10_20/TestDescription.java index e98446086b2..da9366935ff 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_10_20/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_10_20/TestDescription.java @@ -34,6 +34,7 @@ * @requires vm.gc != "G1" | !vm.opt.final.ClassUnloadingWithConcurrentMark * @requires vm.gc != "ConcMarkSweep" * @requires vm.gc != "Z" + * @requires vm.compMode != "Xcomp" * @library /vmTestbase /test/lib * @run driver jdk.test.lib.FileInstaller . . * @run main/othervm diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_70_80/TestDescription.java b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_70_80/TestDescription.java index 0a85f107f9a..cd50bf5d121 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_70_80/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_70_80/TestDescription.java @@ -34,6 +34,7 @@ * @requires vm.gc != "G1" | !vm.opt.final.ClassUnloadingWithConcurrentMark * @requires vm.gc != "ConcMarkSweep" * @requires vm.gc != "Z" + * @requires vm.compMode != "Xcomp" * @library /vmTestbase /test/lib * @run driver jdk.test.lib.FileInstaller . . * @run main/othervm diff --git a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_99_100/TestDescription.java b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_99_100/TestDescription.java index 17e9fe5e402..040867166d2 100644 --- a/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_99_100/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/metaspace/gc/watermark_99_100/TestDescription.java @@ -34,6 +34,7 @@ * @requires vm.gc != "G1" | !vm.opt.final.ClassUnloadingWithConcurrentMark * @requires vm.gc != "ConcMarkSweep" * @requires vm.gc != "Z" + * @requires vm.compMode != "Xcomp" * @library /vmTestbase /test/lib * @run driver jdk.test.lib.FileInstaller . . * @run main/othervm diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load001/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load001/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load001/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load002/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load002/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load003/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load003/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load004/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load004/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load004/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load005/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load005/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load005/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load006/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load006/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load006/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load007/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load007/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load007/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load008/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load008/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load008/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load009/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load009/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load009/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load010/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load010/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load010/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load011/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load011/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load011/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load012/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load012/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/load012/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload001/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload001/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload001/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload002/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload002/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload003/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload003/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload004/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload004/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload004/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload005/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload005/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload005/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload006/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload006/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload006/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload007/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload007/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload007/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload008/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload008/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload008/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload009/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload009/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload009/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload010/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload010/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload010/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload011/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload011/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload011/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload012/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload012/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/classload/unload012/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon001/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon001/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon001/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon002/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon002/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon003/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/cmon003/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace001/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace002/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace002/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace002/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace003/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace003/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace003/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace004/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace004/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace004/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace005/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace005/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace005/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace006/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace006/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace006/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace007/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace007/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace007/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace008/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace008/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace008/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace009/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace009/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace009/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace010/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace010/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace010/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace011/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace011/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace011/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace012/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace012/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace012/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace013/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace013/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace013/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace014/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace014/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace014/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace015/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace015/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace015/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace016/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace016/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace016/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace017/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace017/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace017/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace018/TEST.properties b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace018/TEST.properties deleted file mode 100644 index 04b22a107ac..00000000000 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/stress/thread/strace018/TEST.properties +++ /dev/null @@ -1,23 +0,0 @@ -# -# Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. -# -# 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. -# -exclusiveAccess.dirs=. diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java b/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java index 4a260fc3dd9..83c41e2f82d 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/share/Log.java @@ -79,15 +79,15 @@ public class Log extends FinalizableObject { /** * Is log-mode verbose? - * Default value is false. + * Always enabled. */ - private boolean verbose = false; + private final boolean verbose = true; /** * Should log messages prefixed with timestamps? - * Default value is false. + * Always enabled. */ - private boolean timestamp = false; + private final boolean timestamp = true; /** * Names for trace levels @@ -210,7 +210,6 @@ public Log(PrintStream stream) { */ public Log(PrintStream stream, boolean verbose) { this(stream); - this.verbose = verbose; } /** @@ -221,7 +220,6 @@ public Log(PrintStream stream, boolean verbose) { public Log(PrintStream stream, ArgumentParser argsParser) { this(stream, argsParser.verbose()); traceLevel = argsParser.getTraceLevel(); - timestamp = argsParser.isTimestamp(); } ///////////////////////////////////////////////////////////////// @@ -265,10 +263,9 @@ public void enableVerboseOnError(boolean enable) { * Enable or disable verbose mode for printing messages. */ public void enableVerbose(boolean enable) { - if (!verbose) { - flushLogBuffer(); + if (!enable) { + throw new RuntimeException("The non-verbose logging is not supported."); } - verbose = enable; } public int getTraceLevel() { @@ -467,7 +464,6 @@ private void logExceptionForFailureAnalysis(String msg) { protected synchronized void logTo(PrintStream stream) { finalize(); // flush older log stream out = stream; - verbose = true; } ///////////////////////////////////////////////////////////////// diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 468e9db60c6..017622b61f7 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -143,6 +143,7 @@ java/awt/Frame/UnfocusableMaximizedFrameResizablity/UnfocusableMaximizedFrameRes java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java 7080150 macosx-all java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java 8168646 generic-all java/awt/KeyboardFocusmanager/TypeAhead/TestDialogTypeAhead.java 8198626 macosx-all +java/awt/KeyboardFocusmanager/ConsumeNextMnemonicKeyTypedTest/ConsumeNextMnemonicKeyTypedTest.java 8321303 linux-all java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java 8049405 macosx-all java/awt/Mixing/AWT_Mixing/OpaqueOverlappingChoice.java 8048171 generic-all java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java 8159451 linux-all,windows-all,macosx-all @@ -566,7 +567,7 @@ java/nio/file/WatchService/Basic.java 7158947 solaris- java/nio/file/WatchService/MayFlies.java 7158947 solaris-all Solaris 11 java/nio/file/WatchService/LotsOfCancels.java 8188039 solaris-all Solaris 11 java/nio/file/WatchService/LotsOfEvents.java 7158947 solaris-all Solaris 11 - +java/nio/file/Files/probeContentType/Basic.java 8320943 windows-all ############################################################################ @@ -607,6 +608,12 @@ sun/security/pkcs11/ec/TestKeyFactory.java 8026976 generic- sun/security/pkcs11/KeyStore/ClientAuth.sh 8254806 solaris-all sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8161536 generic-all +javax/net/ssl/SSLEngine/TestAllSuites.java 8298874 generic-all +javax/net/ssl/SSLEngine/EngineCloseOnAlert.java 8298868 generic-all +javax/net/ssl/SSLEngine/ConnectionTest.java 8298869 generic-all +javax/net/ssl/SSLEngine/CheckStatus.java 8298872 generic-all +javax/net/ssl/SSLEngine/Basics.java 8298867 generic-all + javax/net/ssl/DTLS/PacketLossRetransmission.java 8169086 macosx-x64 javax/net/ssl/DTLS/RespondToRetransmit.java 8169086 macosx-all javax/net/ssl/DTLS/CipherSuite.java 8202059 macosx-x64 @@ -636,6 +643,8 @@ sun/security/provider/PolicyParser/PrincipalExpansionError.java 8039280 generic- sun/security/tools/keytool/NssTest.java 8204203 linux-all,windows-all +security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java#teliasonerarootcav1 8333640 generic-all + ############################################################################ # jdk_sound @@ -664,7 +673,7 @@ javax/swing/plaf/basic/BasicTextUI/8001470/bug8001470.java 8233177 linux-all,win javax/swing/JComponent/7154030/bug7154030.java 7190978 generic-all javax/swing/JComboBox/ConsumedKeyTest/ConsumedKeyTest.java 8067986 generic-all -javax/swing/JComponent/6683775/bug6683775.java 8172337 generic-all +javax/swing/JFrame/MaximizeWindowTest.java 8321289 linux-all javax/swing/JComboBox/6236162/bug6236162.java 8028707 windows-all,macosx-all javax/swing/JButton/8151303/PressedIconTest.java 8198689 macosx-all javax/swing/JWindow/ShapedAndTranslucentWindows/PerPixelTranslucentCanvas.java 8081476 windows-all,macosx-all @@ -686,8 +695,7 @@ javax/swing/JComboBox/8072767/bug8072767.java 8196093 windows-all,macosx-all javax/swing/JComponent/4337267/bug4337267.java 8146451 windows-all javax/swing/JFileChooser/8002077/bug8002077.java 8196094 windows-all,macosx-all javax/swing/JFileChooser/6396844/TwentyThousandTest.java 8058231 generic-all -javax/swing/JList/6462008/bug6462008.java 7156347 generic-all -javax/swing/JPopupMenu/6580930/bug6580930.java 7124313 macosx-all +javax/swing/JFileChooser/8194044/FileSystemRootTest.java 8327236 windows-all javax/swing/JPopupMenu/6800513/bug6800513.java 7184956 macosx-all javax/swing/JPopupMenu/6675802/bug6675802.java 8196097 windows-all javax/swing/JTabbedPane/8007563/Test8007563.java 8051591 generic-all @@ -805,7 +813,7 @@ java/awt/Frame/FrameStateTest/FrameStateTest.html 8203920 macosx-all,linux-all javax/swing/SwingUtilities/TestTextPosInPrint.java 8227025 windows-all java/awt/print/PrinterJob/ScaledText/ScaledText.java 8231226 macosx-all java/awt/print/bug8023392/bug8023392.html 8231231 generic-all -java/awt/font/TextLayout/TestJustification.html 8250791 macosx-all +java/awt/font/TextLayout/TestJustification.java 8250791 macosx-all java/awt/TrayIcon/DragEventSource/DragEventSource.java 8252242 macosx-all java/awt/FileDialog/DefaultFocusOwner/DefaultFocusOwner.java 7187728 macosx-all,linux-all java/awt/FileDialog/RegexpFilterTest/RegexpFilterTest.html 7187728 macosx-all,linux-all @@ -830,8 +838,6 @@ sun/tools/jhsdb/HeapDumpTest.java 8193639 solaris- # jdk_other -com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java 8169942 linux-i586,macosx-all,windows-x64 - com/sun/jndi/dns/ConfigTests/PortUnreachable.java 7164518 macosx-all javax/rmi/ssl/SSLSocketParametersTest.sh 8162906 generic-all diff --git a/test/jdk/com/sun/jndi/ldap/BalancedParentheses.java b/test/jdk/com/sun/jndi/ldap/BalancedParentheses.java index 2b62888f75a..b4ea10313d8 100644 --- a/test/jdk/com/sun/jndi/ldap/BalancedParentheses.java +++ b/test/jdk/com/sun/jndi/ldap/BalancedParentheses.java @@ -24,18 +24,23 @@ /** * @test * @bug 6449574 + * @library /test/lib * @summary Invalid ldap filter is accepted and processed */ import java.io.*; import javax.naming.*; import javax.naming.directory.*; -import java.util.Properties; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.SocketAddress; import java.util.Hashtable; import java.net.Socket; import java.net.ServerSocket; +import jdk.test.lib.net.URIBuilder; + public class BalancedParentheses { // Should we run the client or server in a separate thread? // @@ -54,7 +59,13 @@ public class BalancedParentheses { // If the server prematurely exits, serverReady will be set to true // to avoid infinite hangs. void doServerSide() throws Exception { - ServerSocket serverSock = new ServerSocket(serverPort); + // Create unbound server socket + ServerSocket serverSock = new ServerSocket(); + + // And bind it to the loopback address + SocketAddress sockAddr = new InetSocketAddress( + InetAddress.getLoopbackAddress(), 0); + serverSock.bind(sockAddr); // signal client, it's ready to accecpt connection serverPort = serverSock.getLocalPort(); @@ -106,7 +117,13 @@ void doClientSide() throws Exception { Hashtable env = new Hashtable<>(); env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory"); - env.put(Context.PROVIDER_URL, "ldap://localhost:" + serverPort); + // Construct the provider URL + String providerURL = URIBuilder.newBuilder() + .scheme("ldap") + .loopback() + .port(serverPort) + .build().toString(); + env.put(Context.PROVIDER_URL, providerURL); env.put("com.sun.jndi.ldap.read.timeout", "1000"); // env.put(Context.SECURITY_AUTHENTICATION, "simple"); diff --git a/test/jdk/com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java b/test/jdk/com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java index ea056f25237..e72683391ab 100644 --- a/test/jdk/com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java +++ b/test/jdk/com/sun/jndi/ldap/DeadSSLLdapTimeoutTest.java @@ -21,34 +21,35 @@ * questions. */ -/** +/* * @test - * @run main/othervm DeadSSLLdapTimeoutTest * @bug 8141370 * @key intermittent + * @library /test/lib + * @build DeadSSLSocketFactory + * @run main/othervm DeadSSLLdapTimeoutTest */ -import java.net.Socket; +import java.io.EOFException; +import java.io.IOException; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketAddress; import java.net.SocketTimeoutException; -import java.io.*; -import javax.naming.*; -import javax.naming.directory.*; -import java.util.List; +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; import java.util.Hashtable; -import java.util.ArrayList; import java.util.concurrent.Callable; -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Future; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; +import javax.naming.directory.InitialDirContext; import javax.net.ssl.SSLHandshakeException; -import static java.util.concurrent.TimeUnit.MILLISECONDS; +import jdk.test.lib.net.URIBuilder; + import static java.util.concurrent.TimeUnit.NANOSECONDS; @@ -57,26 +58,26 @@ class DeadServerTimeoutSSLTest implements Callable { Hashtable env; DeadSSLServer server; boolean passed = false; - private int HANGING_TEST_TIMEOUT = 20_000; public DeadServerTimeoutSSLTest(Hashtable env) throws IOException { - this.server = new DeadSSLServer(); + SocketAddress sockAddr = new InetSocketAddress( + InetAddress.getLoopbackAddress(), 0); + this.server = new DeadSSLServer(sockAddr); this.env = env; } - public void performOp(InitialContext ctx) throws NamingException {} - - public void handleNamingException(NamingException e, long start, long end) { + public void handleNamingException(NamingException e) { if (e.getCause() instanceof SocketTimeoutException || e.getCause().getCause() instanceof SocketTimeoutException) { // SSL connect will timeout via readReply using // SocketTimeoutException - e.printStackTrace(); + System.out.println("PASS: Observed expected SocketTimeoutException"); pass(); } else if (e.getCause() instanceof SSLHandshakeException && e.getCause().getCause() instanceof EOFException) { // test seems to be failing intermittently on some // platforms. + System.out.println("PASS: Observed expected SSLHandshakeException/EOFException"); pass(); } else { fail(e); @@ -92,6 +93,7 @@ public void fail() { } public void fail(Exception e) { + System.err.println("FAIL: Unexpected exception was observed:" + e.getMessage()); throw new RuntimeException("Test failed", e); } @@ -106,34 +108,36 @@ boolean shutItDown(InitialContext ctx) { public Boolean call() { InitialContext ctx = null; - ScheduledFuture killer = null; - long start = System.nanoTime(); try { - while(!server.accepting()) - Thread.sleep(200); // allow the server to start up + server.serverStarted.await(); // Wait for the server to start-up Thread.sleep(200); // to be sure - env.put(Context.PROVIDER_URL, "ldap://localhost:" + - server.getLocalPort()); + env.put(Context.PROVIDER_URL, + URIBuilder.newBuilder() + .scheme("ldap") + .loopback() + .port(server.getLocalPort()) + .buildUnchecked().toString() + ); + long start = System.nanoTime(); try { ctx = new InitialDirContext(env); - performOp(ctx); fail(); } catch (NamingException e) { long end = System.nanoTime(); System.out.println(this.getClass().toString() + " - elapsed: " + NANOSECONDS.toMillis(end - start)); - handleNamingException(e, start, end); + handleNamingException(e); } finally { - if (killer != null && !killer.isDone()) - killer.cancel(true); + // Stop the server side thread + server.testDone.countDown(); shutItDown(ctx); server.close(); } return passed; - } catch (IOException|InterruptedException e) { + } catch (IOException | InterruptedException e) { throw new RuntimeException(e); } } @@ -141,20 +145,69 @@ public Boolean call() { class DeadSSLServer extends Thread { ServerSocket serverSock; - boolean accepting = false; - - public DeadSSLServer() throws IOException { - this.serverSock = new ServerSocket(0); + // Latch to be used by client to wait for server to start + CountDownLatch serverStarted = new CountDownLatch(1); + + // Latch to be used by server thread to wait for client to finish testing + CountDownLatch testDone = new CountDownLatch(1); + + public DeadSSLServer(SocketAddress socketAddress) throws IOException { + // create unbound server socket + var srvSock = new ServerSocket(); + // bind it to the address provided + srvSock.bind(socketAddress); + this.serverSock = srvSock; start(); } public void run() { - while(true) { - try { - accepting = true; - Socket socket = serverSock.accept(); + // Signal client to proceed with the test + serverStarted.countDown(); + while (true) { + try (var acceptedSocket = serverSock.accept()) { + System.err.println("Accepted connection:" + acceptedSocket); + int iteration = 0; + // Wait for socket to get opened by DeadSSLSocketFactory and connected to the test server + while (iteration++ < 20) { + if (DeadSSLSocketFactory.firstCreatedSocket.get() != null && + DeadSSLSocketFactory.firstCreatedSocket.get().isConnected()) { + break; + } + try { + TimeUnit.MILLISECONDS.sleep(50); + } catch (InterruptedException ie) { + } + } + Socket clientSideSocket = DeadSSLSocketFactory.firstCreatedSocket.get(); + System.err.printf("Got SSLSocketFactory connection after %d iterations: %s%n", + iteration, clientSideSocket); + + if (clientSideSocket == null || !clientSideSocket.isConnected()) { + // If after 1000 ms client side connection is not opened - probably other local process + // tried to connect to the test server socket. Close current connection and retry accept. + continue; + } else { + // Check if accepted socket is connected to the LDAP client + if (acceptedSocket.getLocalPort() == clientSideSocket.getPort() && + acceptedSocket.getPort() == clientSideSocket.getLocalPort() && + acceptedSocket.getInetAddress().equals(clientSideSocket.getLocalAddress())) { + System.err.println("Accepted connection is originated from LDAP client:" + acceptedSocket); + try { + // Give LDAP client time to fully establish the connection. + // When client is done - the accepted socket will be closed + testDone.await(); + } catch (InterruptedException e) { + } + break; + } else { + // If accepted socket is not from the LDAP client - the accepted connection will be closed and new + // one will be accepted + System.err.println("SSLSocketFactory connection has been established, but originated not from" + + " the test's LDAP client:" + acceptedSocket); + } + } } catch (Exception e) { - break; + System.err.println("Server socket. Failure to accept connection:" + e.getMessage()); } } } @@ -163,28 +216,26 @@ public int getLocalPort() { return serverSock.getLocalPort(); } - public boolean accepting() { - return accepting; - } - public void close() throws IOException { serverSock.close(); } } public class DeadSSLLdapTimeoutTest { + // com.sun.jndi.ldap.connect.timeout value to set + static final String CONNECT_TIMEOUT_MS = "10"; + + // com.sun.jndi.ldap.read.timeout value to set + static final String READ_TIMEOUT_MS = "3000"; static Hashtable createEnv() { Hashtable env = new Hashtable<>(11); env.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); + "com.sun.jndi.ldap.LdapCtxFactory"); return env; } public static void main(String[] args) throws Exception { - - InitialContext ctx = null; - // // Running this test serially as it seems to tickle a problem // on older kernels @@ -193,19 +244,24 @@ public static void main(String[] args) throws Exception { // and ssl enabled // this should exit with a SocketTimeoutException as the root cause // it should also use the connect timeout instead of the read timeout - System.out.println("Running connect timeout test with 10ms connect timeout, 3000ms read timeout & SSL"); + System.out.printf("Running connect timeout test with %sms connect timeout," + + " %sms read timeout & SSL%n", + CONNECT_TIMEOUT_MS, READ_TIMEOUT_MS); + Hashtable sslenv = createEnv(); - sslenv.put("com.sun.jndi.ldap.connect.timeout", "10"); - sslenv.put("com.sun.jndi.ldap.read.timeout", "3000"); + // Setup connect timeout environment property + sslenv.put("com.sun.jndi.ldap.connect.timeout", CONNECT_TIMEOUT_MS); + // Setup read timeout environment property + sslenv.put("com.sun.jndi.ldap.read.timeout", READ_TIMEOUT_MS); + // Setup DeadSSLSocketFactory to track the client's first LDAP connection + sslenv.put("java.naming.ldap.factory.socket", "DeadSSLSocketFactory"); + // Use SSL protocol sslenv.put(Context.SECURITY_PROTOCOL, "ssl"); - boolean testFailed = - (new DeadServerTimeoutSSLTest(sslenv).call()) ? false : true; + boolean testFailed = !new DeadServerTimeoutSSLTest(sslenv).call(); if (testFailed) { throw new AssertionError("some tests failed"); } - } - } diff --git a/test/jdk/com/sun/jndi/ldap/DeadSSLSocketFactory.java b/test/jdk/com/sun/jndi/ldap/DeadSSLSocketFactory.java new file mode 100644 index 00000000000..2966abe9554 --- /dev/null +++ b/test/jdk/com/sun/jndi/ldap/DeadSSLSocketFactory.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * 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.net.SocketFactory; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.IOException; +import java.net.InetAddress; +import java.net.Socket; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; + +/* + * A custom socket factory used to override the default socket factory and track the LDAP client connection. + * Factory can create only one SSLSocket. See the DeadServerTimeoutSSLTest test. + */ +public class DeadSSLSocketFactory extends SocketFactory { + // Client socket that is used by LDAP connection + public static AtomicReference firstCreatedSocket = new AtomicReference<>(); + + // Boolean to track if connection socket has been opened + public static AtomicBoolean isConnectionOpened = new AtomicBoolean(false); + + // Default SSLSocketFactory that will be used for SSL socket creation + final SSLSocketFactory factory = (SSLSocketFactory)SSLSocketFactory.getDefault(); + + // Create unconnected socket + public Socket createSocket() throws IOException { + if (!isConnectionOpened.getAndSet(true)) { + System.err.println("DeadSSLSocketFactory: Creating unconnected socket"); + firstCreatedSocket.set((SSLSocket) factory.createSocket()); + return firstCreatedSocket.get(); + } else { + throw new RuntimeException("DeadSSLSocketFactory only allows creation of one SSL socket"); + } + } + + public DeadSSLSocketFactory() { + System.err.println("DeadSSLSocketFactory: Constructor call"); + } + + public static SocketFactory getDefault() { + System.err.println("DeadSSLSocketFactory: acquiring DeadSSLSocketFactory as default socket factory"); + return new DeadSSLSocketFactory(); + } + + @Override + public Socket createSocket(String host, int port) throws IOException { + // Not used by DeadSSLLdapTimeoutTest + return factory.createSocket(host, port); + } + + @Override + public Socket createSocket(String host, int port, InetAddress localHost, + int localPort) throws IOException { + // Not used by DeadSSLLdapTimeoutTest + return factory.createSocket(host, port, localHost, localPort); + } + + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + // Not used by DeadSSLLdapTimeoutTest + return factory.createSocket(host, port); + } + + @Override + public Socket createSocket(InetAddress address, int port, + InetAddress localAddress, int localPort) throws IOException { + // Not used by DeadSSLLdapTimeoutTest + return factory.createSocket(address, port, localAddress, localPort); + } +} + diff --git a/test/jdk/com/sun/jndi/ldap/blits/AddTests/AddNewEntry.java b/test/jdk/com/sun/jndi/ldap/blits/AddTests/AddNewEntry.java index 92528677453..3b9f7c1b9a5 100644 --- a/test/jdk/com/sun/jndi/ldap/blits/AddTests/AddNewEntry.java +++ b/test/jdk/com/sun/jndi/ldap/blits/AddTests/AddNewEntry.java @@ -27,7 +27,7 @@ * @summary Verify capability to add a new entry to the directory using the * ADD operation. * @modules java.naming/com.sun.jndi.ldap - * @library ../../lib/ /javax/naming/module/src/test/test/ + * @library /test/lib ../../lib/ /javax/naming/module/src/test/test/ * @build LDAPServer LDAPTestUtils * @run main/othervm AddNewEntry */ @@ -41,19 +41,36 @@ import javax.naming.directory.InitialDirContext; import javax.naming.directory.SearchControls; import javax.naming.directory.SearchResult; +import java.net.InetAddress; +import java.net.InetSocketAddress; import java.net.ServerSocket; +import java.net.SocketAddress; import java.util.Hashtable; +import jdk.test.lib.net.URIBuilder; public class AddNewEntry { public static void main(String[] args) throws Exception { - ServerSocket serverSocket = new ServerSocket(0); + // Create unbound server socket + ServerSocket serverSocket = new ServerSocket(); + + // Bind it to the loopback address + SocketAddress sockAddr = new InetSocketAddress( + InetAddress.getLoopbackAddress(), 0); + serverSocket.bind(sockAddr); + + // Construct the provider URL for LDAPTestUtils + String providerURL = URIBuilder.newBuilder() + .scheme("ldap") + .loopback() + .port(serverSocket.getLocalPort()) + .buildUnchecked().toString(); Hashtable env; // initialize test - env = LDAPTestUtils - .initEnv(serverSocket, AddNewEntry.class.getName(), args, true); + env = LDAPTestUtils.initEnv(serverSocket, providerURL, + AddNewEntry.class.getName(), args, true); /* Build attribute set */ String[] ids = { "objectClass", "sn", "cn", "telephoneNumber", "mail", diff --git a/test/jdk/com/sun/jndi/ldap/lib/LDAPTestUtils.java b/test/jdk/com/sun/jndi/ldap/lib/LDAPTestUtils.java index dc3ec74e06c..c44cc4aed98 100644 --- a/test/jdk/com/sun/jndi/ldap/lib/LDAPTestUtils.java +++ b/test/jdk/com/sun/jndi/ldap/lib/LDAPTestUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,12 +50,17 @@ public class LDAPTestUtils { * Process command line arguments and return properties in a Hashtable. */ public static Hashtable initEnv(String testname, - String[] args) { + String[] args) { return initEnv(null, testname, args, false); } public static Hashtable initEnv(ServerSocket socket, - String testname, String[] args, boolean authInfo) { + String testname, String[] args, boolean authInfo) { + return initEnv(socket, null, testname, args, authInfo); + } + + public static Hashtable initEnv(ServerSocket socket, String providerUrl, + String testname, String[] args, boolean authInfo) { Hashtable env = new Hashtable<>(); String root = "o=IMC,c=US"; @@ -103,8 +108,9 @@ public static Hashtable initEnv(ServerSocket socket, if (socket != null) { env.put(TEST_LDAP_SERVER_THREAD, startLDAPServer(socket, getCaptureFile(testname))); - env.put("java.naming.provider.url", - "ldap://localhost:" + socket.getLocalPort()); + String url = providerUrl != null ? providerUrl : + "ldap://localhost:" + socket.getLocalPort(); + env.put("java.naming.provider.url", url); } else { // for tests which run against remote server or no server // required diff --git a/test/jdk/com/sun/jndi/ldap/objects/RemoteLocationAttributeTest.java b/test/jdk/com/sun/jndi/ldap/objects/RemoteLocationAttributeTest.java new file mode 100644 index 00000000000..171844833c8 --- /dev/null +++ b/test/jdk/com/sun/jndi/ldap/objects/RemoteLocationAttributeTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2022, 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.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.SocketAddress; +import java.util.Hashtable; +import javax.naming.CommunicationException; +import javax.naming.NamingException; +import javax.naming.ServiceUnavailableException; +import javax.naming.directory.DirContext; +import javax.naming.directory.InitialDirContext; + +import jdk.test.lib.net.URIBuilder; + +/** + * @test + * @bug 8290367 + * @summary Check if com.sun.jndi.ldap.object.trustSerialData covers the creation + * of RMI remote objects from the 'javaRemoteLocation' LDAP attribute. + * @modules java.naming/com.sun.jndi.ldap + * @library /test/lib ../lib /javax/naming/module/src/test/test/ + * @build LDAPServer LDAPTestUtils + * + * @run main/othervm RemoteLocationAttributeTest + * @run main/othervm -Dcom.sun.jndi.ldap.object.trustSerialData + * RemoteLocationAttributeTest + * @run main/othervm -Dcom.sun.jndi.ldap.object.trustSerialData=false + * RemoteLocationAttributeTest + * @run main/othervm -Dcom.sun.jndi.ldap.object.trustSerialData=true + * RemoteLocationAttributeTest + * @run main/othervm -Dcom.sun.jndi.ldap.object.trustSerialData=TrUe + * RemoteLocationAttributeTest + */ + +public class RemoteLocationAttributeTest { + + public static void main(String[] args) throws Exception { + // Create unbound server socket + ServerSocket serverSocket = new ServerSocket(); + + // Bind it to the loopback address + SocketAddress sockAddr = new InetSocketAddress( + InetAddress.getLoopbackAddress(), 0); + serverSocket.bind(sockAddr); + + // Construct the provider URL for LDAPTestUtils + String providerURL = URIBuilder.newBuilder() + .scheme("ldap") + .loopback() + .port(serverSocket.getLocalPort()) + .buildUnchecked().toString(); + + Hashtable env; + + // Initialize test environment variables + env = LDAPTestUtils.initEnv(serverSocket, providerURL, + RemoteLocationAttributeTest.class.getName(), args, false); + + DirContext ctx = null; + try (serverSocket) { + System.err.println(env); + // connect to server + ctx = new InitialDirContext(env); + Object lookupResult = ctx.lookup("Test"); + System.err.println("Lookup result:" + lookupResult); + // Test doesn't provide RMI registry running at 127.0.0.1:1097, but if + // there is one running on test host successful result is valid for + // cases when reconstruction allowed. + if (!RECONSTRUCTION_ALLOWED) { + throw new AssertionError("Unexpected successful lookup"); + } + } catch (ServiceUnavailableException | CommunicationException connectionException) { + // The remote location was properly reconstructed but connection to + // RMI endpoint failed: + // ServiceUnavailableException - no open socket on 127.0.0.1:1097 + // CommunicationException - 127.0.0.1:1097 is open, but it is not RMI registry + System.err.println("Got one of connection exceptions:" + connectionException); + if (!RECONSTRUCTION_ALLOWED) { + throw new AssertionError("Reconstruction not blocked, as expected"); + } + } catch (NamingException ne) { + String message = ne.getMessage(); + System.err.printf("Got NamingException with message: '%s'%n", message); + if (RECONSTRUCTION_ALLOWED && EXPECTED_NAMING_EXCEPTION_MESSAGE.equals(message)) { + throw new AssertionError("Reconstruction unexpectedly blocked"); + } + if (!RECONSTRUCTION_ALLOWED && !EXPECTED_NAMING_EXCEPTION_MESSAGE.equals(message)) { + throw new AssertionError("Reconstruction not blocked"); + } + } finally { + LDAPTestUtils.cleanup(ctx); + } + } + + // Reconstruction of RMI remote objects is allowed if 'com.sun.jndi.ldap.object.trustSerialData' + // is set to "true". If the system property is not specified it implies default "false" value + private static final boolean RECONSTRUCTION_ALLOWED = + Boolean.getBoolean("com.sun.jndi.ldap.object.trustSerialData"); + + // NamingException message when reconstruction is not allowed + private static final String EXPECTED_NAMING_EXCEPTION_MESSAGE = "Object deserialization is not allowed"; +} diff --git a/test/jdk/com/sun/jndi/ldap/objects/RemoteLocationAttributeTest.ldap b/test/jdk/com/sun/jndi/ldap/objects/RemoteLocationAttributeTest.ldap new file mode 100644 index 00000000000..88d69223788 --- /dev/null +++ b/test/jdk/com/sun/jndi/ldap/objects/RemoteLocationAttributeTest.ldap @@ -0,0 +1,61 @@ +# +# Copyright (c) 2022, 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. +# + +################################################################################ +# Capture file for RemoteLocationAttributeTest.java +# +# NOTE: This hexadecimal dump of LDAP protocol messages was generated by +# running the RemoteLocationAttributeTest application program against +# a real LDAP server and setting the JNDI/LDAP environment property: +# com.sun.jndi.ldap.trace.ber to activate LDAP message tracing. +# +################################################################################ + +# LDAP BindRequest +0000: 30 0C 02 01 01 60 07 02 01 03 04 00 80 00 0....`........ + +# LDAP BindResponse +0000: 30 0C 02 01 01 61 07 0A 01 00 04 00 04 00 0....a........ + +# LDAP SearchRequest +0000: 30 46 02 01 02 63 24 04 04 54 65 73 74 0A 01 00 0F...c$..Test... +0010: 0A 01 03 02 01 00 02 01 00 01 01 00 87 0B 6F 62 ..............ob +0020: 6A 65 63 74 43 6C 61 73 73 30 00 A0 1B 30 19 04 jectClass0...0.. +0030: 17 32 2E 31 36 2E 38 34 30 2E 31 2E 31 31 33 37 .2.16.840.1.1137 +0040: 33 30 2E 33 2E 34 2E 32 30.3.4.2 + +# LDAP SearchResultEntry +0000: 30 5E 02 01 02 64 59 04 04 54 65 73 74 30 51 30 0^...dY..Test0Q0 +0010: 16 04 0D 6A 61 76 61 43 6C 61 73 73 4E 61 6D 65 ...javaClassName +0020: 31 05 04 03 66 6F 6F 30 37 04 12 6A 61 76 61 52 1...foo07..javaR +0030: 65 6D 6F 74 65 4C 6F 63 61 74 69 6F 6E 31 21 04 emoteLocation1!. +0040: 1F 72 6D 69 3A 2F 2F 31 32 37 2E 30 2E 30 2E 31 .rmi://127.0.0.1 +0050: 3A 31 30 39 37 2F 54 65 73 74 52 65 6D 6F 74 65 :1097/TestRemote + +# LDAP SearchResultDone +0000: 30 0C 02 01 02 65 07 0A 01 00 04 00 04 00 0....e........ + +# LDAP UnbindRequest +0000: 30 22 02 01 03 42 00 A0 1B 30 19 04 17 32 2E 31 0"...B...0...2.1 +0010: 36 2E 38 34 30 2E 31 2E 31 31 33 37 33 30 2E 33 6.840.1.113730.3 +0020: 2E 34 2E 32 .4.2 diff --git a/test/jdk/java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java b/test/jdk/java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java index 4b835b11063..84e5b4d62e4 100644 --- a/test/jdk/java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java +++ b/test/jdk/java/awt/Choice/ChoiceKeyEventReaction/ChoiceKeyEventReaction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -131,7 +131,7 @@ private static void testKeyOnChoice(int button, int key) { if (toolkit.equals("sun.awt.X11.XToolkit") && keyTypedOnTextField) { - throw new RuntimeException("Test failed. (XToolkit/MToolkit). KeyEvent was addressed to TextField."); + throw new RuntimeException("Test failed. (XToolkit). KeyEvent was addressed to TextField."); } System.out.println("Test passed. Unfocusable Choice doesn't react on keys."); diff --git a/test/jdk/java/awt/Choice/NonFocusablePopupMenuTest.java b/test/jdk/java/awt/Choice/NonFocusablePopupMenuTest.java new file mode 100644 index 00000000000..a22d61caa47 --- /dev/null +++ b/test/jdk/java/awt/Choice/NonFocusablePopupMenuTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2007, 2024, 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 6519005 + * @summary regression: Selection the item on the choice don't work properly in vista ultimate. + * @key headful + * @run main NonFocusablePopupMenuTest + */ + +import java.awt.AWTException; +import java.awt.Choice; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.lang.reflect.InvocationTargetException; + +public class NonFocusablePopupMenuTest extends Frame { + Choice choice; + volatile Point pos; + volatile Dimension size; + volatile int selection1, selection2; + + public void performTest() throws AWTException, + InterruptedException, InvocationTargetException { + Robot robot = new Robot(); + robot.setAutoDelay(100); + EventQueue.invokeAndWait(() -> { + choice = new Choice(); + choice.add("111"); + choice.add("222"); + choice.add("333"); + choice.add("444"); + choice.setFocusable(false); + this.add(choice); + this.setLayout(new FlowLayout()); + setSize (200, 200); + setLocationRelativeTo(null); + setVisible(true); + }); + robot.waitForIdle(); + EventQueue.invokeAndWait(() -> { + pos = choice.getLocationOnScreen(); + size = choice.getSize(); + selection1 = choice.getSelectedIndex(); + }); + robot.mouseMove(pos.x + size.width / 2, pos.y + size.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(500); + robot.mouseMove(pos.x + size.width / 2, pos.y + size.height * 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + EventQueue.invokeAndWait(() -> { + selection2 = choice.getSelectedIndex(); + setVisible(false); + dispose(); + }); + if (selection1 == selection2) { + throw new RuntimeException("Can not change choice selection with the mouse click"); + } + } + + public static void main(String[] args) throws AWTException, + InterruptedException, InvocationTargetException { + NonFocusablePopupMenuTest me = new NonFocusablePopupMenuTest(); + me.performTest(); + } +} \ No newline at end of file diff --git a/test/jdk/java/awt/Choice/NonFocusablePopupMenuTest/NonFocusablePopupMenuTest.html b/test/jdk/java/awt/Choice/NonFocusablePopupMenuTest/NonFocusablePopupMenuTest.html deleted file mode 100644 index 37015ec09c0..00000000000 --- a/test/jdk/java/awt/Choice/NonFocusablePopupMenuTest/NonFocusablePopupMenuTest.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - - - SetFontTest - - - -

    SetFontTest
    Bug ID: 5010944

    - -

    See the dialog box (usually in upper left corner) for instructions

    - - - - diff --git a/test/jdk/java/awt/Choice/NonFocusablePopupMenuTest/NonFocusablePopupMenuTest.java b/test/jdk/java/awt/Choice/NonFocusablePopupMenuTest/NonFocusablePopupMenuTest.java deleted file mode 100644 index 4a10184e0d6..00000000000 --- a/test/jdk/java/awt/Choice/NonFocusablePopupMenuTest/NonFocusablePopupMenuTest.java +++ /dev/null @@ -1,214 +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 6519005 - @summary regression: Selection the item on the choice don't work properly in vista ultimate. - @author Dmitry Cherepanov area=awt.choice - @run applet/manual=yesno NonFocusablePopupMenuTest.html -*/ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; - -public class NonFocusablePopupMenuTest extends Applet -{ - public void init() - { - Choice choice = new Choice(); - choice.add("111"); - choice.add("222"); - choice.add("333"); - choice.add("444"); - choice.setFocusable(false); - - this.add(choice); - - this.setLayout (new FlowLayout ()); - - String[] instructions = - { - "1) The applet contains a non-focusable choice, ", - "2) Click on the choice by mouse, try to change the selection of the choice, ", - "3) If it's not possible to change the selection and popup menu is always open ", - " even if you click by mouse on any item of the choice, the test failed, ", - "4) Otherwise, the test passed. " - }; - Sysout.createDialogWithInstructions( instructions ); - - }//End init() - - public void start () - { - - setSize (200,200); - setVisible(true); - validate(); - - }// start() -} - -/* Place other classes related to the test after this line */ - - - - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 80; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - - }// while - - }// for - - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class diff --git a/test/jdk/java/awt/Clipboard/FlavorChangeNotificationTest/Common.java b/test/jdk/java/awt/Clipboard/FlavorChangeNotificationTest/Common.java new file mode 100644 index 00000000000..516f16db053 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/FlavorChangeNotificationTest/Common.java @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2003, 2023, 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.awt.Image; +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.FlavorEvent; +import java.awt.datatransfer.FlavorListener; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; + +public class Common {} + +class FlavorListenerImpl implements FlavorListener { + public boolean notified1, notified2; + private int count; + public void flavorsChanged(FlavorEvent evt) { + switch (count) { + case 0: + notified1 = true; + break; + case 1: + notified2 = true; + break; + } + count++; + System.err.println("listener's " + this + + " flavorChanged() called " + count + " time"); + } + public String toString() { + return "notified1=" + notified1 + " notified2=" + notified2 + + " count=" + count; + } +}; + + class Util { + public static void setClipboardContents(Clipboard cb, + Transferable contents, + ClipboardOwner owner) { + while (true) { + try { + cb.setContents(contents, owner); + return; + } catch (IllegalStateException ise) { + ise.printStackTrace(); + try { + Thread.sleep(100); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + } + } + + public static void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + + public static Image createImage() { + int w = 100; + int h = 100; + int[] pix = new int[w * h]; + + int index = 0; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int red = 127; + int green = 127; + int blue = y > h / 2 ? 127 : 0; + int alpha = 255; + if (x < w / 4 && y < h / 4) { + alpha = 0; + red = 0; + } + pix[index++] = (alpha << 24) | (red << 16) | (green << 8) | blue; + } + } + + return Toolkit + .getDefaultToolkit(). + createImage(new java.awt.image.MemoryImageSource( + w, h, pix, 0, w + )); + } + +} + + +class TransferableUnion implements Transferable { + + private static final DataFlavor[] ZERO_LENGTH_ARRAY = new DataFlavor[0]; + + private final Transferable TRANSF1, TRANSF2; + + private final DataFlavor[] FLAVORS; + + + public TransferableUnion(Transferable t1, Transferable t2) { + if (t1 == null) { + throw new NullPointerException("t1"); + } + if (t2 == null) { + throw new NullPointerException("t2"); + } + + this.TRANSF1 = t1; + this.TRANSF2 = t2; + + java.util.Set flavorSet = new java.util.HashSet<>(); + flavorSet.addAll(java.util.Arrays.asList(t1.getTransferDataFlavors())); + flavorSet.addAll(java.util.Arrays.asList(t2.getTransferDataFlavors())); + + FLAVORS = flavorSet.toArray(ZERO_LENGTH_ARRAY); + } + + /** + * Returns an array of flavors in which this Transferable + * can provide the data. + */ + public DataFlavor[] getTransferDataFlavors() { + return FLAVORS.clone(); + } + + /** + * Returns whether the requested flavor is supported by this + * Transferable. + * + * @param flavor the requested flavor for the data + * @throws NullPointerException if flavor is null + */ + public boolean isDataFlavorSupported(DataFlavor flavor) { + if (flavor == null) { + throw new NullPointerException("flavor"); + } + + return TRANSF1.isDataFlavorSupported(flavor) + || TRANSF2.isDataFlavorSupported(flavor); + } + + /** + * Returns the Transferable's data in the requested + * DataFlavor if possible. + * + * @param flavor the requested flavor for the data + * @return the data in the requested flavor + * @throws UnsupportedFlavorException if the requested data flavor is + * not supported by this Transferable + * @throws IOException if an IOException occurs while + * retrieving the data. + * @throws NullPointerException if flavor is null + */ + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, java.io.IOException { + + if (!isDataFlavorSupported(flavor)) { + throw new UnsupportedFlavorException(flavor); + } + + java.io.IOException ioexc = null; + + if (TRANSF1.isDataFlavorSupported(flavor)) { + try { + return TRANSF1.getTransferData(flavor); + } catch (java.io.IOException exc) { + ioexc = exc; + } + } + + if (TRANSF2.isDataFlavorSupported(flavor)) { + return TRANSF2.getTransferData(flavor); + } + + if (ioexc != null) { + throw ioexc; + } + + // unreachable + return null; + } + +} + +/** + * A Transferable that implements the capability required + * to transfer an Image. + * + * This Transferable properly supports + * DataFlavor.imageFlavor + * and all equivalent flavors. + * No other DataFlavors are supported. + * + * @see java.awt.datatransfer.DataFlavor.imageFlavor + */ +class ImageSelection implements Transferable { + + private static final DataFlavor[] flavors = { DataFlavor.imageFlavor }; + + private Image data; + + /** + * Creates a Transferable capable of transferring + * the specified Image. + */ + public ImageSelection(Image data) { + this.data = data; + } + + /** + * Returns an array of flavors in which this Transferable + * can provide the data. DataFlavor.stringFlavor + * is supported. + * + * @return an array of length one, whose element is DataFlavor. + * imageFlavor + */ + public DataFlavor[] getTransferDataFlavors() { + return flavors.clone(); + } + + /** + * Returns whether the requested flavor is supported by this + * Transferable. + * + * @param flavor the requested flavor for the data + * @return true if flavor is equal to + * DataFlavor.imageFlavor; + * false otherwise + * @throws NullPointerException if flavor is null + */ + public boolean isDataFlavorSupported(DataFlavor flavor) { + for (int i = 0; i < flavors.length; i++) { + if (flavor.equals(flavors[i])) { + return true; + } + } + return false; + } + + /** + * Returns the Transferable's data in the requested + * DataFlavor if possible. If the desired flavor is + * DataFlavor.imageFlavor, or an equivalent flavor, + * the Image representing the selection is + * returned. + * + * @param flavor the requested flavor for the data + * @return the data in the requested flavor, as outlined above + * @throws UnsupportedFlavorException if the requested data flavor is + * not equivalent to DataFlavor.imageFlavor + * @throws IOException if an IOException occurs while + * retrieving the data. By default, ImageSelection + * never throws this exception, but a subclass may. + * @throws NullPointerException if flavor is null + */ + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException, java.io.IOException { + if (flavor.equals(DataFlavor.imageFlavor)) { + return data; + } else { + throw new UnsupportedFlavorException(flavor); + } + } + +} // class ImageSelection + diff --git a/test/jdk/java/awt/Clipboard/FlavorChangeNotificationTest/PrivateClipboardTest.java b/test/jdk/java/awt/Clipboard/FlavorChangeNotificationTest/PrivateClipboardTest.java new file mode 100644 index 00000000000..70e0001ffc2 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/FlavorChangeNotificationTest/PrivateClipboardTest.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2003, 2023, 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 4259272 + @summary tests that notifications on changes to the set of DataFlavors + available on a private clipboard are delivered properly + @build Common + @run main PrivateClipboardTest +*/ + +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; + +public class PrivateClipboardTest { + + public static void main(String[] args) { + new PrivateClipboardTest().start(); + } + + public void start() { + final Clipboard clipboard = new Clipboard("local"); + + final FlavorListenerImpl listener1 = new FlavorListenerImpl(); + clipboard.addFlavorListener(listener1); + + final FlavorListenerImpl listener2 = new FlavorListenerImpl(); + clipboard.addFlavorListener(listener2); + + Util.setClipboardContents(clipboard, + new StringSelection("text1"), null); + Util.sleep(3000); + + clipboard.removeFlavorListener(listener1); + + Util.setClipboardContents(clipboard, + new TransferableUnion(new StringSelection("text2"), + new ImageSelection(Util.createImage())), null); + Util.sleep(3000); + + System.err.println("listener1: " + listener1 + "\nlistener2: " + listener2); + + if (!(listener1.notified1 && listener2.notified1 && !listener1.notified2 + && listener2.notified2)) { + throw new RuntimeException("notifications about flavor " + + "changes delivered incorrectly!"); + } + } +} diff --git a/test/jdk/java/awt/Clipboard/FlavorChangeNotificationTest/SystemClipboardTest.java b/test/jdk/java/awt/Clipboard/FlavorChangeNotificationTest/SystemClipboardTest.java new file mode 100644 index 00000000000..ff19005b8aa --- /dev/null +++ b/test/jdk/java/awt/Clipboard/FlavorChangeNotificationTest/SystemClipboardTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2003, 2023, 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 4259272 + @summary tests that notifications on changes to the set of DataFlavors + available on the system clipboard are delivered properly + @key headful + @modules java.desktop/sun.awt + @build Common + @run main SystemClipboardTest +*/ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; + +import sun.awt.SunToolkit; + +public class SystemClipboardTest { + + private final Clipboard clipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + + private final FlavorListenerImpl listener1 = new FlavorListenerImpl(); + + private final FlavorListenerImpl listener2 = new FlavorListenerImpl(); + + private boolean isListener2Added; + + + public static void main(String[] args) { + new SystemClipboardTest().start(); + } + + public void start() { + Util.setClipboardContents(clipboard, + new StringSelection("text3"), null); + + clipboard.addFlavorListener(listener1); + + final ThreadGroup threadGroup = new ThreadGroup("Test thread group"); + final Object lock = new Object(); + final Runnable runnable = new Runnable() { + public void run() { + SunToolkit.createNewAppContext(); + clipboard.addFlavorListener(listener2); + synchronized (lock) { + isListener2Added = true; + lock.notifyAll(); + } + } + }; + final Thread thread = new Thread(threadGroup, runnable, "Test thread"); + synchronized (lock) { + thread.start(); + while (!isListener2Added) { + try { + lock.wait(); + } catch (InterruptedException ie) { + ie.printStackTrace(); + } + } + } + + Util.setClipboardContents(clipboard, + new TransferableUnion(new StringSelection("text2"), + new ImageSelection(Util.createImage())), + null); + Util.sleep(3000); + + clipboard.removeFlavorListener(listener1); + // must not remove listener2 from this AppContext + + Util.setClipboardContents(clipboard, + new StringSelection("text3"), null); + Util.sleep(3000); + + System.err.println("listener1: " + listener1 + + "\nlistener2: " + listener2); + + if (!(listener1.notified1 + && listener2.notified1 + && !listener1.notified2 + && listener2.notified2)) { + throw new RuntimeException("notifications about flavor " + + "changes delivered incorrectly!"); + } + } +} \ No newline at end of file diff --git a/test/jdk/java/awt/Clipboard/GetAltContentsTest/PrivateClipboardTest.java b/test/jdk/java/awt/Clipboard/GetAltContentsTest/PrivateClipboardTest.java new file mode 100644 index 00000000000..8edc6da559d --- /dev/null +++ b/test/jdk/java/awt/Clipboard/GetAltContentsTest/PrivateClipboardTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2003, 2023, 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 4287795 4790833 + @summary tests new Clipboard methods: getAvailableDataFlavors, + isDataFlavorAvailable, getData + @run main PrivateClipboardTest +*/ + +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.io.IOException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +public class PrivateClipboardTest { + + public static void main(String[] args) { + boolean failed = false; + final Clipboard clipboard = new Clipboard("local"); + + if (clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) { + failed = true; + System.err.println("FAILURE: isDataFlavorAvailable() returns " + + "true for empty clipboard"); + } + + try { + clipboard.getData(DataFlavor.stringFlavor); + failed = true; + System.err.println("FAILURE: getData() does not throw " + + "UnsupportedFlavorException for empty clipboard"); + } catch (UnsupportedFlavorException exc) { + System.err.println("getData() for empty clipboard throw " + + "UnsupportedFlavorException correctly: " + exc); + } catch (IOException exc) { + failed = true; + exc.printStackTrace(); + } + + if (clipboard.getAvailableDataFlavors() == null || + clipboard.getAvailableDataFlavors().length != 0) { + failed = true; + System.err.println("FAILURE: getAvailableDataFlavors() does not " + + "return zero-length array for empty clipboard: " + + Arrays.toString(clipboard.getAvailableDataFlavors())); + } + + final String contentsText = "contents text"; + + clipboard.setContents(new StringSelection(contentsText), null); + + Transferable contents = clipboard.getContents(null); + Set flavorsT = new HashSet<>( + Arrays.asList(contents.getTransferDataFlavors())); + Set flavorsA = new HashSet<>( + Arrays.asList(clipboard.getAvailableDataFlavors())); + System.err.println("getAvailableDataFlavors(): " + flavorsA); + if (!flavorsA.equals(flavorsT)) { + failed = true; + System.err.println( + "FAILURE: getAvailableDataFlavors() returns incorrect " + + "DataFlavors: " + flavorsA + "\nwhile getContents()." + + "getTransferDataFlavors() return: " + flavorsT); + } + + if (!clipboard.isDataFlavorAvailable(DataFlavor.stringFlavor)) { + failed = true; + System.err.println( + "FAILURE: isDataFlavorAvailable(DataFlavor.stringFlavor) " + + "returns false"); + } + + Object data = null; + try { + data = clipboard.getData(DataFlavor.stringFlavor); + } catch (UnsupportedFlavorException exc) { + failed = true; + exc.printStackTrace(); + } catch (IOException exc) { + failed = true; + exc.printStackTrace(); + } + System.err.println("getData(): " + data); + if (!contentsText.equals(data)) { + failed = true; + System.err.println("FAILURE: getData() returns: " + data + + ", that is not equal to: \"" + contentsText + "\""); + } + + if (failed) { + throw new RuntimeException("test failed, for details see output above"); + } + } +} diff --git a/test/jdk/java/awt/Clipboard/LostOwnershipChainTest/PrivateClipboardTest.java b/test/jdk/java/awt/Clipboard/LostOwnershipChainTest/PrivateClipboardTest.java new file mode 100644 index 00000000000..bddfa7ad062 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/LostOwnershipChainTest/PrivateClipboardTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2002, 2023, 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 4683804 + @summary Tests that in ClipboardOwner.lostOwnership() Clipboard.getContents() + returns actual contents of the clipboard and Clipboard.setContents() + can set contents of the clipboard and its owner. The clipboard is + a private clipboard. +*/ + +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; + +public class PrivateClipboardTest { + + public static void main(String[] args) { + PrivateClipboardOwner.run(); + + if (PrivateClipboardOwner.failed) { + throw new RuntimeException("test failed: can not get actual " + + "contents of the clipboard or set owner of the clipboard"); + } else { + System.err.println("test passed"); + } + } +} + +class PrivateClipboardOwner implements ClipboardOwner { + static boolean failed; + + private static final Object LOCK = new Object(); + + private static final int CHAIN_LENGTH = 5; + private final static Clipboard clipboard = + new Clipboard("PrivateClipboard"); + + private int m, id; + + public PrivateClipboardOwner(int m) { this.m = m; id = m; } + + public void lostOwnership(Clipboard cb, Transferable contents) { + System.err.println(id + " lost clipboard ownership"); + + Transferable t = cb.getContents(null); + String msg = null; + try { + msg = (String)t.getTransferData(DataFlavor.stringFlavor); + } catch (Exception e) { + System.err.println(id + " can't getTransferData: " + e); + } + System.err.println(id + " Clipboard.getContents(): " + msg); + if ( ! msg.equals( "" + (m+1) ) ) { + failed = true; + System.err.println( + "Clipboard.getContents() returned incorrect contents!"); + } + + m += 2; + if (m <= CHAIN_LENGTH) { + System.err.println(id + " Clipboard.setContents(): " + m); + cb.setContents(new StringSelection(m + ""), this); + } + + synchronized (LOCK) { + if (m > CHAIN_LENGTH) { + LOCK.notifyAll(); + } + } + } + + public static void run() { + PrivateClipboardOwner cbo1 = new PrivateClipboardOwner(0); + System.err.println(cbo1.m + " Clipboard.setContents(): " + cbo1.m); + clipboard.setContents(new StringSelection(cbo1.m + ""), cbo1); + + PrivateClipboardOwner cbo2 = new PrivateClipboardOwner(1); + + synchronized (LOCK) { + System.err.println(cbo2.m + " Clipboard.setContents(): " + cbo2.m); + clipboard.setContents(new StringSelection(cbo2.m + ""), cbo2); + try { + LOCK.wait(); + } catch (InterruptedException exc) { + exc.printStackTrace(); + } + } + + if (cbo1.m < CHAIN_LENGTH) { + failed = true; + System.err.println("chain of calls of lostOwnership() broken!"); + } + } +} diff --git a/test/jdk/java/awt/Clipboard/LostOwnershipChainTest/SystemClipboardTest.java b/test/jdk/java/awt/Clipboard/LostOwnershipChainTest/SystemClipboardTest.java new file mode 100644 index 00000000000..eb382e99014 --- /dev/null +++ b/test/jdk/java/awt/Clipboard/LostOwnershipChainTest/SystemClipboardTest.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2002, 2023, 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 4683804 + @summary Tests that in ClipboardOwner.lostOwnership() Clipboard.getContents() + returns actual contents of the clipboard and Clipboard.setContents() + can set contents of the clipboard and its owner. The clipboard is + the system clipboard. + @key headful +*/ + +import java.awt.Toolkit; +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.ClipboardOwner; +import java.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; + +public class SystemClipboardTest { + + public static void main(String[] args) { + SystemClipboardOwner.run(); + + if (SystemClipboardOwner.failed) { + throw new RuntimeException("test failed: can not get actual " + + "contents of the clipboard or set owner of the clipboard"); + } else { + System.err.println("test passed"); + } + } +} + + +class SystemClipboardOwner implements ClipboardOwner { + static boolean failed; + + private static final Object LOCK = new Object(); + + private static final int CHAIN_LENGTH = 5; + private final static Clipboard clipboard = + Toolkit.getDefaultToolkit().getSystemClipboard(); + + private int m, id; + + public SystemClipboardOwner(int m) { this.m = m; id = m; } + + public void lostOwnership(Clipboard cb, Transferable contents) { + System.err.println(id + " lost clipboard ownership"); + + Transferable t = getClipboardContents(cb, null); + String msg = null; + try { + msg = (String)t.getTransferData(DataFlavor.stringFlavor); + } catch (Exception e) { + System.err.println(id + " can't getTransferData: " + e); + } + System.err.println(id + " Clipboard.getContents(): " + msg); + if ( ! msg.equals( "" + (m+1) ) ) { + failed = true; + System.err.println( + "Clipboard.getContents() returned incorrect contents!"); + } + + m += 2; + if (m <= CHAIN_LENGTH) { + System.err.println(id + " Clipboard.setContents(): " + m); + setClipboardContents(cb, new StringSelection(m + ""), this); + } + + synchronized (LOCK) { + if (m > CHAIN_LENGTH) { + LOCK.notifyAll(); + } + } + } + + public static void run() { + SystemClipboardOwner cbo1 = new SystemClipboardOwner(0); + System.err.println(cbo1.m + " Clipboard.setContents(): " + cbo1.m); + setClipboardContents(clipboard, + new StringSelection(cbo1.m + ""), cbo1); + + SystemClipboardOwner cbo2 = new SystemClipboardOwner(1); + synchronized (LOCK) { + System.err.println(cbo2.m + " Clipboard.setContents(): " + cbo2.m); + setClipboardContents(clipboard, + new StringSelection(cbo2.m + ""), cbo2); + try { + LOCK.wait(); + } catch (InterruptedException exc) { + exc.printStackTrace(); + } + } + + if (cbo1.m < CHAIN_LENGTH) { + failed = true; + System.err.println("chain of calls of lostOwnership() broken!"); + } + } + + private static void setClipboardContents(Clipboard cb, + Transferable contents, + ClipboardOwner owner) { + synchronized (cb) { + while (true) { + try { + cb.setContents(contents, owner); + return; + } catch (IllegalStateException ise) { + try { Thread.sleep(100); } + catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + } + + private static Transferable getClipboardContents(Clipboard cb, + Object requestor) { + synchronized (cb) { + while (true) { + try { + return cb.getContents(requestor); + } catch (IllegalStateException ise) { + try { Thread.sleep(100); } + catch (InterruptedException e) { e.printStackTrace(); } + } + } + } + } + +} diff --git a/test/jdk/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java b/test/jdk/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java index f5d85d8a2ad..c7ec4d66000 100644 --- a/test/jdk/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java +++ b/test/jdk/java/awt/Dialog/NestedDialogs/Modal/NestedModalDialogTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2023, 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 @@ -54,12 +54,11 @@ import java.awt.event.KeyEvent; public class NestedModalDialogTest { - private static Frame frame; + private static StartFrame frame; private static IntermediateDialog interDiag; private static TextDialog txtDiag; // Global variables so the robot thread can locate things. - private static Button[] robot_button = new Button[2]; private static TextField robot_text = null; private static Robot robot = null; @@ -78,6 +77,9 @@ private static void blockTillDisplayed(Component comp) { } private static void clickOnComp(Component comp) { + robot.waitForIdle(); + robot.delay(1000); + Rectangle bounds = new Rectangle(comp.getLocationOnScreen(), comp.getSize()); robot.mouseMove(bounds.x + bounds.width / 2, bounds.y + bounds.height / 2); robot.waitForIdle(); @@ -94,11 +96,11 @@ public void testModalDialogs() throws Exception { // launch first frame with firstButton frame = new StartFrame(); blockTillDisplayed(frame); - clickOnComp(robot_button[0]); + clickOnComp(frame.button); // Dialog must be created and onscreen before we proceed. blockTillDisplayed(interDiag); - clickOnComp(robot_button[1]); + clickOnComp(interDiag.button); // Again, the Dialog must be created and onscreen before we proceed. blockTillDisplayed(robot_text); @@ -144,6 +146,8 @@ public void testModalDialogs() throws Exception { */ class StartFrame extends Frame { + public volatile Button button; + /** * Constructs a new instance. */ @@ -168,7 +172,7 @@ public void actionPerformed(ActionEvent e) { pan.add(but); add(pan); setVisible(true); - robot_button[0] = but; + button = but; } } @@ -177,6 +181,7 @@ public void actionPerformed(ActionEvent e) { class IntermediateDialog extends Dialog { Dialog m_parent; + public volatile Button button; public IntermediateDialog(Frame parent) { super(parent, "Intermediate Modal", true /*Modal*/); @@ -193,9 +198,7 @@ public void actionPerformed(ActionEvent e) { pan.add(but); add(pan); pack(); - - // The robot needs to know about us, so set global - robot_button[1] = but; + button = but; } } @@ -215,12 +218,12 @@ public TextDialog(Dialog parent) { } } - public static void main(String[] args) throws RuntimeException, Exception { + public static void main(String[] args) throws Exception { try { new NestedModalDialogTest().testModalDialogs(); } catch (Exception e) { throw new RuntimeException("NestedModalDialogTest object creation " - + "failed"); + + "failed", e); } } } diff --git a/test/jdk/java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java b/test/jdk/java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java index 959c90b6997..13a3db5bbf4 100644 --- a/test/jdk/java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java +++ b/test/jdk/java/awt/FileDialog/FilenameFilterTest/FilenameFilterTest.java @@ -28,7 +28,7 @@ @summary namefilter is not called for file dialog on windows @library ../../regtesthelpers @build Util - @run main FilenameFilterTest + @run main/othervm FilenameFilterTest */ import java.awt.*; diff --git a/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java b/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java index a87b59a9388..1e5b2789208 100644 --- a/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java +++ b/test/jdk/java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowBlockingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -69,11 +69,6 @@ public void eventDispatched(AWTEvent e) { } public void start() { - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("No testing on Motif. Test passed."); - return; - } - System.out.println("\nTest started:\n"); // Test 1. diff --git a/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java b/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java index 0a7a1afff61..45914e0670b 100644 --- a/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java +++ b/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -293,43 +293,39 @@ public void run() { // 6. Show unblocking modal Dialog. /////////////////////////////////// - if ("sun.awt.motif.MToolkit".equals(toolkitClassName)) { - System.out.println("Stage 6 - Skiping."); - } else { - System.out.println("Stage 6 in progress..."); + System.out.println("Stage 6 in progress..."); - // --- - // Testing the bug of activating invisible modal Dialog (awt_Window::SetAndActivateModalBlocker). - // Having some window not excluded from modality, so that it would be blocked. - Frame f = new Frame("Aux. Frame"); - f.setSize(100, 100); - setVisible(f, true); - // --- + // --- + // Testing the bug of activating invisible modal Dialog (awt_Window::SetAndActivateModalBlocker). + // Having some window not excluded from modality, so that it would be blocked. + Frame f = new Frame("Aux. Frame"); + f.setSize(100, 100); + setVisible(f, true); + // --- - setVisible(focusedFrame, true); + setVisible(focusedFrame, true); + if (!focusOwner.hasFocus()) { + Util.clickOnComp(focusOwner, robot); + Util.waitForIdle(robot); if (!focusOwner.hasFocus()) { - Util.clickOnComp(focusOwner, robot); - Util.waitForIdle(robot); - if (!focusOwner.hasFocus()) { - throw new Error("Test error: the frame couldn't be focused."); - } + throw new Error("Test error: the frame couldn't be focused."); } + } - dialog.setModal(true); - dialog.setAutoRequestFocus(false); - focusedFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); + dialog.setModal(true); + dialog.setAutoRequestFocus(false); + focusedFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); - TestHelper.invokeLaterAndWait(new Runnable() { - public void run() { - dialog.setVisible(true); - } - }, robot); + TestHelper.invokeLaterAndWait(new Runnable() { + public void run() { + dialog.setVisible(true); + } + }, robot); - if (dialog.isFocused()) { - throw new TestFailedException("the unblocking dialog shouldn't gain focus but it did!"); - } - setVisible(dialog, false); + if (dialog.isFocused()) { + throw new TestFailedException("the unblocking dialog shouldn't gain focus but it did!"); } + setVisible(dialog, false); System.out.println("Test passed."); } diff --git a/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java b/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java index 8ca4d4d6f7b..b1b8b8458ff 100644 --- a/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java +++ b/test/jdk/java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -202,26 +202,22 @@ public void start() { // Focused frame is excluded from modality. //////////////////////////////////////////////// - if (!"sun.awt.motif.MToolkit".equals(toolkitClassName)) { - recreateGUI(); - auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); + recreateGUI(); + auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); - Test.setWindows(modalDialog, modalDialog, new Window[] {modalDialog, frame3}); - Test.test("Test stage 6.1 in progress", modalDlgButton); - } + Test.setWindows(modalDialog, modalDialog, new Window[] {modalDialog, frame3}); + Test.test("Test stage 6.1 in progress", modalDlgButton); // 6.2. Owner Frame (with owned modal Dialog). // Focused frame is excluded from modality. //////////////////////////////////////////////// - if (!"sun.awt.motif.MToolkit".equals(toolkitClassName)) { - recreateGUI(); - auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); + recreateGUI(); + auxFrame.setModalExclusionType(Dialog.ModalExclusionType.APPLICATION_EXCLUDE); - Test.setWindows(frame3, modalDialog, new Window[] {modalDialog, frame3}); - Test.test("Test stage 6.2 in progress", modalDlgButton, true); - } + Test.setWindows(frame3, modalDialog, new Window[] {modalDialog, frame3}); + Test.test("Test stage 6.2 in progress", modalDlgButton, true); /////////////////////////////////////////////////// // 7. Calling setVisible(true) for the shown Frame. @@ -422,4 +418,3 @@ class TestFailedException extends RuntimeException { super("Test failed: " + msg); } } - diff --git a/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.java b/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.java index 9a0d476133b..27be25773f2 100644 --- a/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.java +++ b/test/jdk/java/awt/Focus/ModalBlockedStealsFocusTest/ModalBlockedStealsFocusTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,11 +47,6 @@ public static void main(String[] args) { } public void start() { - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("The test is not for MToolkit."); - return; - } - dialog.setBounds(800, 0, 200, 100); frame.setBounds(800, 150, 200, 100); diff --git a/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java b/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java index 0ee37cbce69..7cfe66834bc 100644 --- a/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java +++ b/test/jdk/java/awt/Focus/ModalExcludedWindowClickTest/ModalExcludedWindowClickTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -57,12 +57,6 @@ public void init() { } public void start() { - - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("No testing on MToolkit."); - return; - } - button.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { actionPerformed = true; diff --git a/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java b/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java index b6d4c962efa..abf8d57cecd 100644 --- a/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java +++ b/test/jdk/java/awt/Focus/NonFocusableBlockedOwnerTest/NonFocusableBlockedOwnerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -56,12 +56,6 @@ public void init() { } public void start() { - - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("No testing on MToolkit."); - return; - } - try { EventQueue.invokeLater(new Runnable() { public void run() { diff --git a/test/jdk/java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java b/test/jdk/java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java index cfabc697f85..7b552424f8d 100644 --- a/test/jdk/java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java +++ b/test/jdk/java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2024, 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 @@ -21,20 +21,29 @@ * questions. */ -/* - @test - @key headful - @bug 6182359 - @summary Tests that Window having non-focusable owner can't be a focus owner. - @library ../../regtesthelpers - @build Util - @run main NonfocusableOwnerTest -*/ - -import java.awt.*; -import java.awt.event.*; import test.java.awt.regtesthelpers.Util; +import java.awt.AWTEvent; +import java.awt.Button; +import java.awt.Dialog; +import java.awt.Frame; +import java.awt.KeyboardFocusManager; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.AWTEventListener; +import java.awt.event.FocusEvent; +import java.awt.event.WindowEvent; + +/* + ( @test + * @key headful + * @bug 6182359 + * @summary Tests that Window having non-focusable owner can't be a focus owner. + * @library ../../regtesthelpers + * @build Util + * @run main NonfocusableOwnerTest + */ public class NonfocusableOwnerTest { Robot robot = Util.createRobot(); Frame frame; @@ -55,7 +64,7 @@ public void eventDispatched(AWTEvent e) { } }, FocusEvent.FOCUS_EVENT_MASK | WindowEvent.WINDOW_FOCUS_EVENT_MASK | WindowEvent.WINDOW_EVENT_MASK); - frame = new Frame("Frame"); + frame = new Frame("NonfocusableOwnerTest"); frame.setName("Frame-owner"); frame.setBounds(100, 0, 100, 100); dialog = new Dialog(frame, "Dialog"); @@ -92,9 +101,11 @@ void test1(Window owner, Window child) { owner.setFocusableWindowState(false); owner.setVisible(true); + robot.waitForIdle(); child.add(button); child.setVisible(true); + robot.waitForIdle(); Util.waitTillShown(child); @@ -111,12 +122,15 @@ void test2(Window owner, Window child1, Window child2) { owner.setFocusableWindowState(false); owner.setVisible(true); + robot.waitForIdle(); child1.setFocusableWindowState(true); child1.setVisible(true); + robot.waitForIdle(); child2.add(button); child2.setVisible(true); + robot.waitForIdle(); Util.waitTillShown(child2); @@ -134,13 +148,16 @@ void test3(Window owner, Window child1, Window child2) { owner.setFocusableWindowState(true); owner.setVisible(true); + robot.waitForIdle(); child1.setFocusableWindowState(false); child1.setVisible(true); + robot.waitForIdle(); child2.setFocusableWindowState(true); child2.add(button); child2.setVisible(true); + robot.waitForIdle(); Util.waitTillShown(child2); diff --git a/test/jdk/java/awt/Focus/OwnedWindowFocusIMECrashTest/OwnedWindowFocusIMECrashTest.java b/test/jdk/java/awt/Focus/OwnedWindowFocusIMECrashTest/OwnedWindowFocusIMECrashTest.java index 6fe6b6a1fa5..f81b25cb1d4 100644 --- a/test/jdk/java/awt/Focus/OwnedWindowFocusIMECrashTest/OwnedWindowFocusIMECrashTest.java +++ b/test/jdk/java/awt/Focus/OwnedWindowFocusIMECrashTest/OwnedWindowFocusIMECrashTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,7 @@ public void start() { window.setVisible(true); Util.waitForIdle(robot); + robot.delay(1000); test(); diff --git a/test/jdk/java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java b/test/jdk/java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java index 0a2ed310c17..2e386fd1c6d 100644 --- a/test/jdk/java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java +++ b/test/jdk/java/awt/Focus/SimpleWindowActivationTest/SimpleWindowActivationTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -56,12 +56,6 @@ public class SimpleWindowActivationTest { private static Robot robot; public static void main(String[] args) throws Exception { - - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("No testing on Motif. Test passed."); - return; - } - robot = new Robot(); robot.setAutoDelay(50); diff --git a/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java b/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java index 962f6b4665c..6a6cfc93939 100644 --- a/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java +++ b/test/jdk/java/awt/Focus/WindowUpdateFocusabilityTest/WindowUpdateFocusabilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -63,11 +63,6 @@ public void init() { } public void start() { - if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - System.out.println("No testing on Motif."); - return; - } - test(new Frame("Frame owner")); Frame dialog_owner = new Frame("dialog's owner"); test(new Dialog(dialog_owner)); diff --git a/test/jdk/java/awt/Frame/DefaultSizeTest.java b/test/jdk/java/awt/Frame/DefaultSizeTest.java new file mode 100644 index 00000000000..a1a6ec7477f --- /dev/null +++ b/test/jdk/java/awt/Frame/DefaultSizeTest.java @@ -0,0 +1,65 @@ +/* + * Copyright (c) 1998, 2023, 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.awt.EventQueue; +import java.awt.Frame; + +/* + * @test 4033151 + * @summary Test that frame default size is minimum possible size + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual DefaultSizeTest + */ + +public class DefaultSizeTest { + + private static final String INSTRUCTIONS = "An empty frame is created.\n" + + "It should be located to the right of this window\n" + + "and should be the minimum size allowed by the window manager.\n" + + "For any WM, the frame should be very small.\n" + + "If the frame is not large, click Pass or Fail otherwise."; + + + public static void main(String[] args) throws Exception { + PassFailJFrame passFailJFrame = new PassFailJFrame.Builder() + .title("DefaultSizeTest Instructions Frame") + .instructions(INSTRUCTIONS) + .testTimeOut(5) + .rows(10) + .columns(45) + .build(); + + EventQueue.invokeAndWait(() -> { + Frame frame = new Frame("DefaultSize"); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame + .positionTestWindow(frame, PassFailJFrame.Position.HORIZONTAL); + + frame.setVisible(true); + }); + + passFailJFrame.awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/Frame/GetBoundsResizeTest.java b/test/jdk/java/awt/Frame/GetBoundsResizeTest.java new file mode 100644 index 00000000000..d3c2ffb0bad --- /dev/null +++ b/test/jdk/java/awt/Frame/GetBoundsResizeTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1998, 2024, 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.awt.Button; +import java.awt.Frame; +import java.awt.EventQueue; +import java.awt.Robot; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; + +/* + * @test + * @bug 4103095 + * @summary Test for getBounds() after a Frame resize. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual GetBoundsResizeTest +*/ + +public class GetBoundsResizeTest { + private static final String INSTRUCTIONS = """ + 0. There is a test window with a "Press" button, + Its original bounds should be printed in the text area below. + 1. Resize the test window using the upper left corner. + 2. Press the button to print the result of getBounds() to the text area. + 3. Previously, a window could report an incorrect position on the + screen after resizing the window in this way. + If getBounds() prints the appropriate values for the window, + click Pass, otherwise click Fail. + """; + + private static JTextArea textArea; + private static Frame frame; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + + PassFailJFrame passFailJFrame = PassFailJFrame + .builder() + .title("GetBoundsResizeTest Instructions") + .instructions(INSTRUCTIONS) + .splitUIBottom(() -> { + textArea = new JTextArea("", 8, 55); + textArea.setEditable(false); + return new JScrollPane(textArea); + }) + .testUI(GetBoundsResizeTest::getFrame) + .rows((int) (INSTRUCTIONS.lines().count() + 2)) + .columns(40) + .build(); + + robot.waitForIdle(); + robot.delay(500); + + EventQueue.invokeAndWait(() -> + logFrameBounds("Original Frame.getBounds() = %s\n")); + + passFailJFrame.awaitAndCheck(); + } + + private static Frame getFrame() { + frame = new Frame("GetBoundsResizeTest"); + + Button button = new Button("Press"); + button.addActionListener((e) -> + logFrameBounds("Current Frame.getBounds() = %s\n")); + + frame.add(button); + frame.setSize(200, 100); + + return frame; + } + + private static void logFrameBounds(String format) { + textArea.append(format.formatted(frame.getBounds())); + } +} diff --git a/test/jdk/java/awt/Frame/GetBoundsResizeTest/GetBoundsResizeTest.java b/test/jdk/java/awt/Frame/GetBoundsResizeTest/GetBoundsResizeTest.java deleted file mode 100644 index 9dad65ddd2c..00000000000 --- a/test/jdk/java/awt/Frame/GetBoundsResizeTest/GetBoundsResizeTest.java +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 1998, 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 4103095 - @summary Test for getBounds() after a Frame resize. - @author andrei.dmitriev : area=awt.toplevel - @run main/manual GetBoundsResizeTest -*/ - -import java.applet.Applet; -import java.lang.*; -import java.awt.*; -import java.awt.event.*; - -class Globals { - static boolean testPassed=false; - static Thread mainThread=null; -} - -public class GetBoundsResizeTest extends Applet { - - public static void main(String args[]) throws Exception { - GetBoundsResizeTest app = new GetBoundsResizeTest(); - app.start(); - Globals.mainThread = Thread.currentThread(); - try { - Thread.sleep(300000); - } catch (InterruptedException e) { - if (!Globals.testPassed) - throw new Exception("GetBoundsResizeTest failed."); - } - } - - public void start() - { - String[] message = { - "Resize the window using the upper left corner.", - "Press the button to print the result of getBounds() to the terminal.", - "If getBounds() prints the correct values for the window", - "then click Pass, else click Fail." - }; - new TestDialog(new Frame(), "GetBoundsResizeTest", message).start(); - new GetBoundsResizeTester("GetBoundsResizeTester").start(); - } -} - -//////////////////////////////////////////////////////////////////////// -// Test Dialog -//////////////////////////////////////////////////////////////////////// - -class TestDialog extends Dialog - implements ActionListener { - - static TextArea output; - Button passButton; - Button failButton; - String name; - - public TestDialog(Frame frame, String name, String[] message) - { - super(frame, name + " Pass/Fail Dialog"); - this.name = name; - int maxStringLength = 0; - for (int i=0; i { + try { + // Need a peer anyway, so let the bug manifest visuially, even + // though we can detect it automatically. + f = new Frame(); + p = new Panel(); + p.setBackground(Color.red); + f.setLayout (new BorderLayout ()); + f.add(p, "Center"); + + Insets insetsBefore = p.getInsets(); + insetsBefore.top = SENTINEL_INSET_VALUE; + + Insets insetsAfter = p.getInsets(); + if (insetsAfter.top == SENTINEL_INSET_VALUE) { // OOPS! + throw new Error("4198994: getInsets returns the same object on subsequent invocations"); + } + + f.setSize (200,200); + f.setLocationRelativeTo(null); + f.setVisible(true); + + System.out.println("getInsets is ok. The object it returns is safe to modify."); + } finally { + if (f != null) { + f.dispose(); + } + } + }); + } +} diff --git a/test/jdk/java/awt/Insets/RemoveMenuBarTest.java b/test/jdk/java/awt/Insets/RemoveMenuBarTest.java new file mode 100644 index 00000000000..d6285ee3176 --- /dev/null +++ b/test/jdk/java/awt/Insets/RemoveMenuBarTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2006, 2023, 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 6353381 + @summary REG: Container.getInsets() returns an incorrect value after removal of menubar, Win32 + @key headful + @run main RemoveMenuBarTest +*/ +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Insets; +import java.awt.Menu; +import java.awt.MenuBar; + +public class RemoveMenuBarTest { + static Frame frame; + + public static void main(String[] args) throws Exception { + EventQueue.invokeAndWait(() -> { + try { + // old insets: top>0 | left>0 + // new insets: top=0 & left=0 + // the bug is that updating doesn't happen + frame = new Frame(); + MenuBar menubar = new MenuBar(); + frame.setBounds(100,100,100,100); + frame.setUndecorated(true); + frame.pack(); + menubar.add(new Menu()); + frame.setMenuBar(menubar); + System.out.println(frame.getInsets()); + + frame.setMenuBar(null); + Insets insets = frame.getInsets(); + System.out.println(insets); + if (insets.top != 0 || insets.left != 0 || + insets.bottom !=0 || insets.right != 0) { + throw new RuntimeException("Test failed: the incorrect insets"); + } + } finally { + if (frame != null) { + frame.dispose(); + } + } + }); + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_utils.cpp b/test/jdk/java/awt/Insets/SetInsetsTest.java similarity index 57% rename from test/hotspot/jtreg/vmTestbase/nsk/share/native/native_utils.cpp rename to test/jdk/java/awt/Insets/SetInsetsTest.java index ae937b615ec..c1177160958 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/native/native_utils.cpp +++ b/test/jdk/java/awt/Insets/SetInsetsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2023, 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 @@ -20,24 +20,26 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -#include - -#if (defined(WIN32) || defined (_WIN32) ) -#include -#define getpid _getpid -#define pidType int -#else -#include -#define pidType pid_t -#endif - -#include -#include - -extern "C" { +/* + @test + @bug 4704042 + @summary Unit tests for Insets.set() + @run main SetInsetsTest +*/ +import java.awt.Insets; +import java.awt.EventQueue; -JNIEXPORT jlong -JNICALL Java_nsk_share_NativeUtils_getCurrentPID(JNIEnv * jni, jobject jobj) { - return (jlong) getpid(); -} -} +public class SetInsetsTest { + public static void main(String[] args) throws Exception { + EventQueue.invokeAndWait(() -> { + Insets insets = new Insets(0,0,0,0); + insets.set(100,100,100,100); + if (insets.top != 100 || + insets.bottom != 100 || + insets.left != 100 || + insets.right != 100) { + throw new RuntimeException("Test Failed! Insets=" + insets); + } + }); + } +}// class SetInsetsTest diff --git a/test/jdk/java/awt/Insets/WindowInsetsTest.java b/test/jdk/java/awt/Insets/WindowInsetsTest.java new file mode 100644 index 00000000000..56abfecdc43 --- /dev/null +++ b/test/jdk/java/awt/Insets/WindowInsetsTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2004, 2023, 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 5089312 + @summary Bottom inset must not change after a second pack call. + @key headful + @run main WindowInsetsTest +*/ +import java.awt.EventQueue; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JWindow; + +public class WindowInsetsTest { + static JFrame frame; + static JWindow window; + + public static void main(String[] args) throws Exception { + EventQueue.invokeAndWait(() -> { + try { + frame = new JFrame("Window Test"); + frame.setBounds(100, 100, 400, 300); + frame.setVisible(true); + + JButton button = new JButton("A Button"); + window = new JWindow(frame); + window.getContentPane().add(button); + window.pack(); + window.setLocation(200, 200); + window.show(); + double h0 = window.getSize().getHeight(); + window.pack(); + double h1 = window.getSize().getHeight(); + if( Math.abs(h1 - h0) > 0.5 ) { + throw new RuntimeException("Test failed: Bad insets."); + } + System.out.println("Test Passed."); + } finally { + if (window != null) { + window.dispose(); + } + if (frame != null) { + frame.dispose(); + } + } + }); + } +} diff --git a/test/jdk/java/awt/LightweightComponent/LightweightCliprect.java b/test/jdk/java/awt/LightweightComponent/LightweightCliprect.java new file mode 100644 index 00000000000..af59629d1b2 --- /dev/null +++ b/test/jdk/java/awt/LightweightComponent/LightweightCliprect.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 1998, 2023, 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.awt.Color; +import java.awt.Component; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Shape; + +/* + * @test + * @bug 4116029 + * @summary drawString does not honor clipping regions for lightweight components + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual LightweightCliprect + */ + +public class LightweightCliprect { + + private static final String INSTRUCTIONS = "If some text is drawn outside the red rectangle, press \"Fail\" button.\n" + + "Otherwise, press \"Pass\" button."; + + public static void main(String[] args) throws Exception { + PassFailJFrame passFailJFrame = new PassFailJFrame.Builder() + .title("LightweightCliprect Instructions Frame") + .instructions(INSTRUCTIONS) + .testTimeOut(5) + .rows(10) + .columns(45) + .build(); + + EventQueue.invokeAndWait(() -> { + Frame frame = new Frame("DefaultSize"); + + Container panel = new MyContainer(); + MyComponent c = new MyComponent(); + panel.add(c); + + frame.add(panel); + frame.setSize(400, 300); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame + .positionTestWindow(frame, PassFailJFrame.Position.HORIZONTAL); + + frame.setVisible(true); + }); + + passFailJFrame.awaitAndCheck(); + } +} + +class MyComponent extends Component { + + public void paint(Graphics g) { + Color c = g.getColor(); + g.setColor(Color.red); + g.fillRect(20, 20, 400, 200); + Shape clip = g.getClip(); + g.setClip(20, 20, 400, 200); + //draw the current java version in the component + g.setColor(Color.black); + String version = System.getProperty("java.version"); + String vendor = System.getProperty("java.vendor"); + int y = 10; + for(int i = 0; i < 30; i++) { + g.drawString("Lightweight: Java version: " + version + + ", Vendor: " + vendor, 10, y += 20); + } + g.setColor(c); + g.setClip(clip); + super.paint(g); + } + + public Dimension getPreferredSize() { + return new Dimension(300, 300); + } +} + +class MyContainer extends Container { + public MyContainer() { + super(); + setLayout(new FlowLayout()); + } + + public void paint(Graphics g) { + Rectangle bounds = new Rectangle(getSize()); + g.setColor(Color.cyan); + g.drawRect(bounds.x, bounds.y, bounds.width - 1, bounds.height - 1); + super.paint(g); + } +} diff --git a/test/jdk/java/awt/List/ISCAfterRemoveAllTest.java b/test/jdk/java/awt/List/ISCAfterRemoveAllTest.java new file mode 100644 index 00000000000..e853ac2e1e4 --- /dev/null +++ b/test/jdk/java/awt/List/ISCAfterRemoveAllTest.java @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2005, 2023, 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 6291736 + @summary ITEM_STATE_CHANGED triggered after List.removeAll(), XToolkit + @key headful + @run main ISCAfterRemoveAllTest +*/ + +import java.awt.AWTException; +import java.awt.FlowLayout; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.KeyboardFocusManager; +import java.awt.List; +import java.awt.Point; +import java.awt.Robot; + +import java.awt.event.InputEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; + +public class ISCAfterRemoveAllTest implements ItemListener { + List list; + Frame frame; + volatile boolean passed = true; + + public static void main(String[] args) throws Exception { + ISCAfterRemoveAllTest test = new ISCAfterRemoveAllTest(); + test.start(); + } + + public void start () throws Exception { + try { + EventQueue.invokeAndWait(() -> { + list = new List(4, false); + frame = new Frame("ISCAfterRemoveAllTest"); + list.add("000"); + list.add("111"); + list.add("222"); + list.add("333"); + list.add("444"); + list.add("555"); + list.add("666"); + list.add("777"); + list.add("888"); + list.add("999"); + + frame.add(list); + frame.setLayout(new FlowLayout()); + frame.setSize(300, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private void test() throws Exception { + Robot r = new Robot(); + r.delay(1000); + r.waitForIdle(); + EventQueue.invokeAndWait(() -> { + Point loc = list.getLocationOnScreen(); + r.mouseMove(loc.x + list.getWidth() / 2, loc.y + list.getHeight() / 2); + }); + r.delay(100); + r.mousePress(InputEvent.BUTTON1_MASK); + r.delay(10); + r.mouseRelease(InputEvent.BUTTON1_MASK); + r.delay(100); + + EventQueue.invokeAndWait(() -> { + list.removeAll(); + + // The interesting events are generated after removing + list.addItemListener(this); + r.delay(100); + + list.requestFocusInWindow(); + r.delay(100); + if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != list) { + throw new RuntimeException("Test failed - list isn't focus owner."); + } + }); + + r.delay(10); + r.keyPress(KeyEvent.VK_UP); + r.delay(10); + r.keyRelease(KeyEvent.VK_UP); + r.delay(100); + + // This is the test case for the 6299853 issue + r.delay(10); + r.keyPress(KeyEvent.VK_SPACE); + r.delay(10); + r.keyRelease(KeyEvent.VK_SPACE); + r.delay(100); + + r.waitForIdle(); + + if (!passed) { + throw new RuntimeException("Test failed."); + } + } + + public void itemStateChanged(ItemEvent ie) { + System.out.println(ie); + // We shouldn't generate any events since the list is empty + passed = false; + } + +} diff --git a/test/jdk/java/awt/List/InstanceOfSelectedArray.java b/test/jdk/java/awt/List/InstanceOfSelectedArray.java new file mode 100644 index 00000000000..28bfe7cd877 --- /dev/null +++ b/test/jdk/java/awt/List/InstanceOfSelectedArray.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2002, 2023, 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 4322321 + @summary tests that List.getSelectedIndexes() doesn't return reference to internal array + @key headful + @run main InstanceOfSelectedArray +*/ + +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; + +public class InstanceOfSelectedArray { + List testList; + Frame frame; + int[] selected; + + public static void main(String[] args) throws Exception { + InstanceOfSelectedArray test = new InstanceOfSelectedArray(); + test.start(); + } + + public void start () throws Exception { + try { + EventQueue.invokeAndWait(() -> { + testList = new List(); + frame = new Frame("InstanceOfSelectedArrayTest"); + testList.addItem("First"); + testList.addItem("Second"); + testList.addItem("Third"); + + frame.add(testList); + frame.setLayout(new FlowLayout()); + frame.setSize(300, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + + testList.select(2); + + selected = testList.getSelectedIndexes(); + selected[0] = 0; + selected = testList.getSelectedIndexes(); + + if (selected[0] == 0) { + System.out.println("List returned the reference to internal array."); + System.out.println("Test FAILED"); + throw new RuntimeException("Test FAILED"); + } + }); + + System.out.println("List returned a clone of its internal array."); + System.out.println("Test PASSED"); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/List/ListEnterExitTest.java b/test/jdk/java/awt/List/ListEnterExitTest.java new file mode 100644 index 00000000000..998b152a634 --- /dev/null +++ b/test/jdk/java/awt/List/ListEnterExitTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (c) 1999, 2023, 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 4274839 4281703 + @summary tests that List receives mouse enter/exit events properly + @key headful + @run main ListEnterExitTest +*/ + +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.List; +import java.awt.Point; +import java.awt.Robot; + +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +public class ListEnterExitTest { + final List list = new List(); + final MouseEnterExitListener mouseEnterExitListener = new MouseEnterExitListener(); + Frame frame; + volatile Point p; + + public static void main(String[] args) throws Exception { + ListEnterExitTest test = new ListEnterExitTest(); + test.start(); + } + + public void start() throws Exception { + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("ListEnterExitTest"); + list.add("Item 1"); + list.add("Item 2"); + list.addMouseListener(mouseEnterExitListener); + frame.add(list); + frame.setLayout(new FlowLayout()); + frame.setSize(300, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + final Robot robot = new Robot(); + robot.delay(1000); + robot.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + p = list.getLocationOnScreen(); + }); + robot.mouseMove(p.x + 10, p.y + 10); + robot.delay(100); + robot.waitForIdle(); + robot.mouseMove(p.x - 10, p.y - 10); + robot.delay(100); + robot.waitForIdle(); + robot.mouseMove(p.x + 10, p.y + 10); + + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + + synchronized (mouseEnterExitListener) { + mouseEnterExitListener.wait(2000); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + if (!mouseEnterExitListener.isPassed()) { + throw new RuntimeException("Haven't receive mouse enter/exit events"); + } + + } + +} + +class MouseEnterExitListener extends MouseAdapter { + + volatile boolean passed_1 = false; + volatile boolean passed_2 = false; + + public void mouseEntered(MouseEvent e) { + passed_1 = true; + } + + public void mouseExited(MouseEvent e) { + passed_2 = true; + } + + public void mousePressed(MouseEvent e) { + synchronized (this) { + System.out.println("mouse pressed"); + this.notifyAll(); + } + } + + public boolean isPassed() { + return passed_1 & passed_2; + } +} diff --git a/test/jdk/java/awt/List/ListNullTest.java b/test/jdk/java/awt/List/ListNullTest.java new file mode 100644 index 00000000000..60e84f8aacd --- /dev/null +++ b/test/jdk/java/awt/List/ListNullTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (c) 1998, 2023, 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 4195583 + @summary Tests List.add(String item) to make sure an NPE is not thrown + when item == null + @key headful + @run main ListNullTest +*/ + +import java.awt.FlowLayout; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.List; +import java.awt.Robot; + +public class ListNullTest { + List list; + Frame frame; + + public static void main(String[] args) throws Exception { + ListNullTest test = new ListNullTest(); + test.start(); + } + + public void start () throws Exception { + try { + EventQueue.invokeAndWait(() -> { + list = new List(15); + frame = new Frame("ListNullTest"); + frame.add(list); + frame.setLayout(new FlowLayout()); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + list.add("", 0); + list.add((String) null, 1); + }); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/List/MaxWidthTest.java b/test/jdk/java/awt/List/MaxWidthTest.java new file mode 100644 index 00000000000..d200ddb14aa --- /dev/null +++ b/test/jdk/java/awt/List/MaxWidthTest.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2006, 2023, 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 6373369 + @summary Bug in WListPeer.getMaxWidth(), checks that the preferred width + of the list is calculated correctly + @requires (os.family == "windows") + @key headful + @run main MaxWidthTest +*/ + +import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.FontMetrics; +import java.awt.List; +import java.awt.TextArea; +import java.awt.Toolkit; + +public class MaxWidthTest { + static Frame frame; + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("MaxWidthTest"); + frame.setLayout(new BorderLayout()); + List list = new List(); + list.add("Very very very long string - the actual width more than the minimum width !!!"); + frame.add(BorderLayout.WEST, list); + frame.add(BorderLayout.CENTER, new TextArea()); + + frame.setBounds(200, 200, 200, 200); + frame.pack(); + frame.setVisible(true); + + // as WListPeer.minimumSize() - just predefined value + FontMetrics fm = frame.getFontMetrics(list.getFont()); + int minimum = 20 + fm.stringWidth("0123456789abcde"); + + // as WListPeer.preferredSize() - equals to Max.max(minimum,getMaxWidth()+20) + // getMaxWidth() returns the actual size of the list + int preferred = list.getPreferredSize().width; + + System.out.println(preferred + "," + minimum); + if (preferred <= minimum) { + throw new RuntimeException("Test failed because the actual width more than the minimum width."); + } + }); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/List/PageUPSelectsItemsTest.java b/test/jdk/java/awt/List/PageUPSelectsItemsTest.java new file mode 100644 index 00000000000..2d742d07e5c --- /dev/null +++ b/test/jdk/java/awt/List/PageUPSelectsItemsTest.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2005, 2023, 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 6190768 + @summary Tests that pressing pg-up / pg-down on AWT list doesn't selects the items, on XToolkit + @key headful + @run main PageUPSelectsItemsTest +*/ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.KeyboardFocusManager; +import java.awt.Label; +import java.awt.List; +import java.awt.Point; +import java.awt.Robot; + +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.KeyListener; + +import java.lang.reflect.InvocationTargetException; + +public class PageUPSelectsItemsTest implements FocusListener, KeyListener { + + List list = new List(6, true); + Label label = new Label("for focus"); + + Frame frame; + + final Object LOCK = new Object(); + final int ACTION_TIMEOUT = 500; + + public static void main(String[] args) throws Exception { + PageUPSelectsItemsTest test = new PageUPSelectsItemsTest(); + test.start(); + } + + public void start() throws Exception { + try { + EventQueue.invokeAndWait(() -> { + list.add("0"); + list.add("1"); + list.add("2"); + list.add("3"); + list.add("4"); + list.add("5"); + list.add("6"); + list.add("7"); + list.add("8"); + list.add("9"); + list.add("10"); + list.add("11"); + list.add("12"); + + list.select(8); + + list.addFocusListener(this); + list.addKeyListener(this); + frame = new Frame("PageUPSelectsItemsTest"); + frame.setLayout(new BorderLayout()); + frame.add(BorderLayout.SOUTH, list); + frame.add(BorderLayout.CENTER, label); + frame.setSize(300, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private void test() throws Exception { + synchronized (LOCK) { + + Robot r = new Robot(); + r.delay(500); + + Point loc = label.getLocationOnScreen(); + r.mouseMove(loc.x + (int) (label.getWidth() / 2), loc.y + (int) (label.getHeight() / 2)); + r.mousePress(InputEvent.BUTTON1_MASK); + r.delay(10); + r.mouseRelease(InputEvent.BUTTON1_MASK); + r.delay(500); + + list.requestFocusInWindow(); + LOCK.wait(ACTION_TIMEOUT); + if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != list) { + throw new RuntimeException("Test failed - list isn't focus owner."); + } + + r.delay(10); + loc = list.getLocationOnScreen(); + + r.delay(50); + r.keyPress(KeyEvent.VK_PAGE_UP); + r.delay(50); + r.keyRelease(KeyEvent.VK_PAGE_UP); + r.delay(50); + + r.keyPress(KeyEvent.VK_PAGE_DOWN); + r.delay(50); + r.keyRelease(KeyEvent.VK_PAGE_DOWN); + r.delay(50); + + r.waitForIdle(); + EventQueue.invokeAndWait(new Runnable() { + public void run() { + System.out.println("Dummy block"); + } + }); + + System.err.println("Selected objects: " + list.getSelectedItems().length); + + if (list.getSelectedItems().length > 1) { + throw new RuntimeException("Test failed"); + } + } + } + + public void focusGained(FocusEvent e) { + + synchronized (LOCK) { + LOCK.notifyAll(); + } + + } + + public void focusLost(FocusEvent e) { + } + + public void keyPressed(KeyEvent e){ + System.out.println("keyPressed-"+e); + } + + public void keyReleased(KeyEvent e){ + System.out.println("keyReleased-"+e); + } + + public void keyTyped(KeyEvent e){ + System.out.println("keyTyped-"+e); + } +} diff --git a/test/jdk/java/awt/List/TriggerActionEventTest.java b/test/jdk/java/awt/List/TriggerActionEventTest.java new file mode 100644 index 00000000000..32ae5c184df --- /dev/null +++ b/test/jdk/java/awt/List/TriggerActionEventTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2005, 2023, 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 6190746 + @summary Tests that list trigger ActionEvent when double clicking a programmatically selected item, XToolkit + @key headful + @run main TriggerActionEventTest +*/ + +import java.awt.AWTException; +import java.awt.BorderLayout; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.List; +import java.awt.Point; +import java.awt.Robot; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; + +import java.lang.reflect.InvocationTargetException; + +public class TriggerActionEventTest implements ActionListener { + final Object LOCK = new Object(); + final int ACTION_TIMEOUT = 1000; + + List list; + Frame frame; + volatile Point loc; + private volatile boolean passed = false; + + public static void main(String[] args) throws Exception { + TriggerActionEventTest TrgrActnEvntTest = new TriggerActionEventTest(); + TrgrActnEvntTest.test(new TestState(0)); + TrgrActnEvntTest.test(new TestState(3)); + } + + private void test(TestState currentState) throws Exception { + + synchronized (LOCK) { + System.out.println("begin test for: " + currentState); + + EventQueue.invokeAndWait(() -> { + list = new List(); + + list.clear(); + list.add("0"); + list.add("1"); + list.add("2"); + list.add("3"); + list.addActionListener(this); + + int index = currentState.getSelectedIndex(); + + list.select(index); + + frame = new Frame("TriggerActionEventTest"); + frame.setLayout(new BorderLayout()); + frame.add(BorderLayout.SOUTH, list); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + + Robot r = new Robot(); + r.delay(500); + EventQueue.invokeAndWait(() -> { + loc = list.getLocationOnScreen(); + }); + + r.mouseMove(loc.x + 10, loc.y + 10); + r.mousePress(InputEvent.BUTTON1_MASK); + r.delay(10); + r.mouseRelease(InputEvent.BUTTON1_MASK); + r.mousePress(InputEvent.BUTTON1_MASK); + r.delay(10); + r.mouseRelease(InputEvent.BUTTON1_MASK); + r.delay(10); + + + LOCK.wait(ACTION_TIMEOUT); + + System.out.println(currentState); + if (!passed) { + throw new RuntimeException("Test failed"); + } + this.passed = false; + + EventQueue.invokeAndWait(() -> { + list.removeActionListener(this); + frame.remove(list); + frame.setVisible(false); + }); + + } + } + + public void actionPerformed (ActionEvent ae) { + synchronized (LOCK) { + System.out.println(ae); + passed = true; + LOCK.notifyAll(); + } + } + +} + +class TestState { + private final int selectedIndex; + + public TestState(int selectedIndex) { + this.selectedIndex = selectedIndex; + } + + public int getSelectedIndex() { + return selectedIndex; + } + + public String toString() { + return ""+selectedIndex; + } + +} diff --git a/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_1.java b/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_1.java new file mode 100644 index 00000000000..808bb598cec --- /dev/null +++ b/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_1.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 1998, 2023, 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.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4028130 + * @summary Test dynamically adding and removing a menu bar + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AddRemoveMenuBarTest_1 + */ + +public class AddRemoveMenuBarTest_1 { + + private static final String INSTRUCTIONS = """ + An initially empty frame should appear. + + Click anywhere in the frame to add a menu bar at the top of the frame. + + Click again to replace the menu bar with another menu bar. + + Each menu bar has one (empty) menu, labelled with the + number of the menu bar appearing. + + After a menubar is added, the frame should not be resized nor repositioned + on the screen; + + it should have the same size and position. + + Upon test completion, click Pass or Fail appropriately. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame passFailJFrame = new PassFailJFrame.Builder() + .title("AddRemoveMenuBarTest_1 Instructions") + .instructions(INSTRUCTIONS) + .testTimeOut(5) + .rows(18) + .columns(45) + .build(); + + SwingUtilities.invokeAndWait(() -> { + AddRemoveMenuBar_1 frame = new AddRemoveMenuBar_1(); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, + PassFailJFrame.Position.HORIZONTAL); + + frame.setVisible(true); + }); + + passFailJFrame.awaitAndCheck(); + } +} + +class AddRemoveMenuBar_1 extends Frame { + int menuCount; + + AddRemoveMenuBar_1() { + super("AddRemoveMenuBar_1"); + setSize(200, 200); + menuCount = 0; + + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + setMenuBar(); + } + }); + } + + void setMenuBar() { + MenuBar bar = new MenuBar(); + bar.add(new Menu(Integer.toString(menuCount++))); + setMenuBar(bar); + } +} diff --git a/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_2.java b/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_2.java new file mode 100644 index 00000000000..c0c98a5ca95 --- /dev/null +++ b/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_2.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 1998, 2023, 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.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4028130 + * @key headful + * @summary Test dynamically adding and removing a menu bar + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AddRemoveMenuBarTest_2 + */ + +public class AddRemoveMenuBarTest_2 { + private static final String INSTRUCTIONS = """ + A frame with a menu bar appears. + + Click anywhere in the frame to replace the menu bar with + another one. + + Each menu bar has one (empty) menu, 'foo'. + + After the menu bar replacement, the containing frame + should not be resized nor repositioned on the screen. + + Upon test completion, click Pass or Fail appropriately. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame passFailJFrame = new PassFailJFrame.Builder() + .title("AddRemoveMenuBarTest_2 Instructions") + .instructions(INSTRUCTIONS) + .testTimeOut(5) + .rows(15) + .columns(45) + .build(); + + SwingUtilities.invokeAndWait(() -> { + AddRemoveMenuBar_2 frame = new AddRemoveMenuBar_2(); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, + PassFailJFrame.Position.HORIZONTAL); + + frame.setVisible(true); + }); + + passFailJFrame.awaitAndCheck(); + } +} + +class AddRemoveMenuBar_2 extends Frame { + AddRemoveMenuBar_2() { + super("AddRemoveMenuBar_2"); + setSize(200, 200); + setMenuBar(); + addMouseListener(new MouseAdapter() { + @Override + public void mouseClicked(MouseEvent e) { + setMenuBar(); + } + }); + } + + int count = 0; + + void setMenuBar() { + MenuBar bar = new MenuBar(); + bar.add(new Menu("foo " + count++)); + super.setMenuBar(bar); + } +} diff --git a/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_3.java b/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_3.java new file mode 100644 index 00000000000..a01ddd9925b --- /dev/null +++ b/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_3.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 1998, 2023, 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.awt.BorderLayout; +import java.awt.Checkbox; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Label; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.Panel; +import java.awt.Rectangle; +import java.awt.TextField; +import java.awt.event.ActionListener; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4017504 + * @summary Test dynamically adding and removing a menu bar + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AddRemoveMenuBarTest_3 + */ + +public class AddRemoveMenuBarTest_3 { + private static final String INSTRUCTIONS = """ + A frame at (100,100) contains two (2) rows of three (3) text + fields each, and under this, a checkbox labelled 'Use menubar'. + + The first row's text fields pertain to the x coordinates and + the second row's text fields pertain to the y coordinates. + + The first column, 'request', is an input only field for frame + location. (press enter to apply). + + The second column, 'reported', is an output only + field reporting frame location. + + The third column, 'inset', is an output only field reporting + the frame's inset values. + + You can click the 'Use menubar' checkbox to alternately add + and remove a menu bar containing an (empty) 'Help' menu. + + After a menubar is added or removed, the frame should not + have been resized nor repositioned on the screen and the + y inset should accurately reflect the presence or absence + of the menubar within the inset. + + The insets always include the window manager's title and border + decorations, if any. + + Upon test completion, click Pass or Fail appropriately. + """; + public static void main(String[] args) throws Exception { + PassFailJFrame passFailJFrame = new PassFailJFrame.Builder() + .title("AddRemoveMenuBarTest_3 Instructions") + .instructions(INSTRUCTIONS) + .testTimeOut(5) + .rows(30) + .columns(38) + .build(); + + SwingUtilities.invokeAndWait(() -> { + AddRemoveMenuBar_3 frame = new AddRemoveMenuBar_3(); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(null, + PassFailJFrame.Position.HORIZONTAL); + + frame.setVisible(true); + }); + + passFailJFrame.awaitAndCheck(); + } +} + +class AddRemoveMenuBar_3 extends Frame { + TextField xfield; + TextField yfield; + + TextField xfield_out; + TextField yfield_out; + TextField xinset_out; + TextField yinset_out; + + Checkbox menu_checkbox; + MenuBar menubar; + + public AddRemoveMenuBar_3() { + super("AddRemoveMenuBar_3"); + + menubar = new MenuBar(); + menubar.setHelpMenu(new Menu("Help")); + + setLayout(new BorderLayout()); + Panel p = new Panel(); + add("Center", p); + p.setLayout(new GridLayout(3, 3)); + + menu_checkbox = new Checkbox("Use menubar"); + add("South", menu_checkbox); + + xfield = new TextField(); + yfield = new TextField(); + xfield_out = new TextField(); + xfield_out.setEditable(false); + xfield_out.setFocusable(false); + yfield_out = new TextField(); + yfield_out.setEditable(false); + yfield_out.setFocusable(false); + + xinset_out = new TextField(); + xinset_out.setEditable(false); + xinset_out.setFocusable(false); + yinset_out = new TextField(); + yinset_out.setEditable(false); + yinset_out.setFocusable(false); + + p.add(new Label("request")); + p.add(new Label("reported")); + p.add(new Label("inset")); + + p.add(xfield); + p.add(xfield_out); + p.add(xinset_out); + + p.add(yfield); + p.add(yfield_out); + p.add(yinset_out); + + setSize(200, 200); + setLocation(100, 100); + + addComponentListener(new ComponentAdapter() { + @Override + public void componentMoved(ComponentEvent e) { + xfield_out.setText(Integer.toString(getLocation().x)); + yfield_out.setText(Integer.toString(getLocation().y)); + + xinset_out.setText(Integer.toString(getInsets().left)); + yinset_out.setText(Integer.toString(getInsets().top)); + } + }); + + ActionListener setLocationListener = e -> { + Rectangle r = getBounds(); + try { + r.x = Integer.parseInt(xfield.getText()); + r.y = Integer.parseInt(yfield.getText()); + } catch (java.lang.NumberFormatException ignored) { + } + + setLocation(r.x, r.y); + }; + + xfield.addActionListener(setLocationListener); + yfield.addActionListener(setLocationListener); + + menu_checkbox.addItemListener(e -> { + if (menu_checkbox.getState()) { + setMenuBar(menubar); + } else { + setMenuBar(null); + } + + validate(); + xinset_out.setText(Integer.toString(getInsets().left)); + yinset_out.setText(Integer.toString(getInsets().top)); + }); + } +} diff --git a/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_4.java b/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_4.java new file mode 100644 index 00000000000..571fce7fba5 --- /dev/null +++ b/test/jdk/java/awt/MenuBar/AddRemoveMenuBarTests/AddRemoveMenuBarTest_4.java @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1998, 2023, 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.awt.Button; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Menu; +import java.awt.MenuBar; +import java.awt.MenuItem; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4071086 + * @key headful + * @summary Test dynamically adding and removing a menu bar + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual AddRemoveMenuBarTest_4 + */ + +public class AddRemoveMenuBarTest_4 { + + private static final String INSTRUCTIONS = """ + There is a frame with a menubar and a single button. + + The button is labelled 'Add new MenuBar'. + + If you click the button, the menubar is replaced with another menubar. + This can be done repeatedly. + + The -th menubar contains one menu, 'TestMenu', + with two items, 'one ' and 'two '. + + Click again to replace the menu bar with another menu bar. + + After a menubar has been replaced with another menubar, + the frame should not be resized nor repositioned on the screen. + + Upon test completion, click Pass or Fail appropriately. + """; + + public static void main(String[] args) throws Exception { + PassFailJFrame passFailJFrame = new PassFailJFrame.Builder() + .title("AddRemoveMenuBarTest_4 Instructions") + .instructions(INSTRUCTIONS) + .testTimeOut(5) + .rows(18) + .columns(45) + .build(); + + SwingUtilities.invokeAndWait(() -> { + AddRemoveMenuBar_4 frame = new AddRemoveMenuBar_4(); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, + PassFailJFrame.Position.HORIZONTAL); + + frame.setVisible(true); + }); + + passFailJFrame.awaitAndCheck(); + } +} + +class AddRemoveMenuBar_4 extends Frame { + int count = 1; + MenuBar mb = null; + + AddRemoveMenuBar_4() { + super("AddRemoveMenuBar_4"); + setLayout(new FlowLayout()); + + Button b = new Button("Add new MenuBar"); + b.addActionListener((e) -> createMenuBar()); + add(b); + + createMenuBar(); + + setSize(300, 300); + } + + void createMenuBar() { + if (mb != null) { + remove(mb); + } + + mb = new MenuBar(); + Menu m = new Menu("TestMenu" + count); + m.add(new MenuItem("one " + count)); + m.add(new MenuItem("two " + count)); + count++; + mb.add(m); + setMenuBar(mb); + } +} diff --git a/test/jdk/java/awt/Modal/BlockedMouseInputTest.java b/test/jdk/java/awt/Modal/BlockedMouseInputTest.java new file mode 100644 index 00000000000..81a4dfcb7b9 --- /dev/null +++ b/test/jdk/java/awt/Modal/BlockedMouseInputTest.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2005, 2023, 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 4957639 + @summary REGRESSION: blocked mouse input in a special case on win32 + @key headful + @run main BlockedMouseInputTest +*/ + +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; + +import java.awt.event.InputEvent; +import java.awt.event.ItemEvent; +import java.awt.event.ItemListener; + +import javax.swing.JComboBox; +import javax.swing.JDialog; +/* + * Threads: + * 0) Main - running others, checking + * 1) First - opening first dialog + * 2) Second - opening second dialog, generating item state changed events + * We need 1 and 2 thread in order to don't block main thread + */ + +public class BlockedMouseInputTest implements ItemListener { + Frame frame = null; + + ThreadDialog thread1 = null; + ThreadDialog thread2 = null; + + // If we recreate dialogs in the Threads classes then the test works fine + JComboBox cb = null; + JDialog dialog1 = null; + JDialog dialog2 = null; + + Robot r = null; + volatile Point loc = null; + volatile int cbWidth; + volatile int cbHeight; + + volatile int selected; + + volatile boolean passed = false; + + public static void main(String[] args) throws Exception { + BlockedMouseInputTest test = new BlockedMouseInputTest(); + test.start(); + } + + public void start() throws Exception { + try { + r = new Robot(); + EventQueue.invokeAndWait(() -> { + frame = new Frame("Parent frame"); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + if (dialog1 != null) { + dialog1.dispose(); + } + if (dialog2 != null) { + dialog2.dispose(); + } + }); + } + } + + private void test() throws Exception { + + // The state of the combobox should stay the same to new iteration of the cycle + // We couldn't run the thread twice + EventQueue.invokeAndWait(() -> { + cb = new JComboBox(new String[]{"entry a", "entry b", + "entry c", "entry d", "entry e"}); + dialog1 = new JDialog(frame, "dialog1", true); + dialog2 = new JDialog(frame, "dialog2", true); + dialog2.getContentPane().add(cb); + cb.addItemListener(this); + + dialog1.setLocation(20, 20); + dialog1.setSize(new Dimension(150, 50)); + dialog2.setLocation(120, 120); + dialog2.setSize(new Dimension(150, 50)); + }); + + for (int i = 0; i < 2; i++) { + passed = false; + tryGenerateEvent(); + if (!passed && i != 0) { + throw new RuntimeException("Test failed: triggering not occurred, iteration - " + i); + } + } + } + + private void tryGenerateEvent() throws Exception { + EventQueue.invokeAndWait(() -> { + thread1 = new ThreadDialog(dialog1); + thread2 = new ThreadDialog(dialog2); + }); + + thread1.start(); + r.delay(500); + r.waitForIdle(); + thread2.start(); + r.delay(500); + r.waitForIdle(); + + doRobotAction(); + + EventQueue.invokeAndWait(() -> { + dialog2.setVisible(false); + dialog1.setVisible(false); + }); + } + + public void itemStateChanged(ItemEvent ie) { + passed = true; + System.out.println("event: "+ie); + } + + public void doRobotAction() throws Exception { + EventQueue.invokeAndWait(() -> { + loc = cb.getLocationOnScreen(); + cbWidth = cb.getWidth(); + cbHeight = cb.getHeight(); + }); + + r.mouseMove(loc.x + cbWidth / 2, loc.y + cbHeight / 2); + r.delay(500); + r.mousePress(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + + EventQueue.invokeAndWait(() -> { + selected = cb.getSelectedIndex(); + }); + + r.mouseMove(loc.x + cbWidth / 2, loc.y + cbHeight * ((selected == 0) ? 2 : 1) + 10); + r.delay(500); + r.mousePress(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + + r.waitForIdle(); + } +} + +class ThreadDialog extends Thread { + + JDialog dialog = null; + + public ThreadDialog(JDialog dialog){ + this.dialog = dialog; + } + + public void run() { + dialog.setVisible(true); + } +} diff --git a/test/jdk/java/awt/Modal/BlockedMouseInputTest2.java b/test/jdk/java/awt/Modal/BlockedMouseInputTest2.java new file mode 100644 index 00000000000..12b56d6fd69 --- /dev/null +++ b/test/jdk/java/awt/Modal/BlockedMouseInputTest2.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2005, 2023, 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 6271546 + @summary REG. Mouse input blocked on a window which is a child of a modal dialog + @key headful + @run main BlockedMouseInputTest2 +*/ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Dialog; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; + +public class BlockedMouseInputTest2 { + Frame frame; + Dialog dlg1; + Dialog dlg2; + Button b; + Robot r = null; + volatile boolean passed = false; + volatile Point p; + volatile int btnWidth; + volatile int btnHeight; + + public static void main(String args[]) throws Exception { + BlockedMouseInputTest2 test = new BlockedMouseInputTest2(); + test.start(); + } + + public void start() throws Exception { + try { + r = new Robot(); + EventQueue.invokeAndWait(() -> { + frame = new Frame("Parent frame"); + frame.setBounds(100, 100, 200, 100); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + + dlg1 = new Dialog(frame, "Dialog 1", true); + dlg1.setBounds(200, 200, 200, 100); + + new Thread(new Runnable() { + public void run() { + dlg1.setVisible(true); + } + }).start(); + }); + + r.delay(1000); + r.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + dlg2 = new Dialog(frame, "Dialog 2", true); + dlg2.setBounds(300, 300, 200, 100); + }); + new Thread(new Runnable() { + public void run() { + dlg2.setVisible(true); + } + }).start(); + + r.delay(1000); + r.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + Dialog d = new Dialog(dlg2, "D", false); + d.setBounds(400, 400, 200, 100); + d.setLayout(new BorderLayout()); + b = new Button("Test me"); + b.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + passed = true; + } + }); + d.add(b, BorderLayout.CENTER); + d.setVisible(true); + }); + + r.delay(1000); + r.waitForIdle(); + + EventQueue.invokeAndWait(() -> { + p = b.getLocationOnScreen(); + btnWidth = b.getSize().width; + btnHeight = b.getSize().height; + }); + r.mouseMove(p.x + btnWidth / 2, p.y + btnHeight / 2); + r.delay(500); + r.mousePress(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + + if (!passed) { + throw new RuntimeException("Test is FAILED: button is not pressed"); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + if (dlg1 != null) { + dlg1.dispose(); + } + if (dlg2 != null) { + dlg2.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/Modal/BlockedMouseInputTest3.java b/test/jdk/java/awt/Modal/BlockedMouseInputTest3.java new file mode 100644 index 00000000000..a7fafa73cf0 --- /dev/null +++ b/test/jdk/java/awt/Modal/BlockedMouseInputTest3.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2005, 2023, 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 6274378 + @summary Test for 6274378: Blocked mouse and keyboard input after hiding modal dialog + @key headful + @run main BlockedMouseInputTest3 +*/ + +import java.awt.Button; +import java.awt.Dialog; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.KeyboardFocusManager; +import java.awt.Point; +import java.awt.Robot; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + + +public class BlockedMouseInputTest3 { + Frame frame; + + Dialog dlg1; // application-modal + Dialog dlg2; // application-modal + Dialog d; // toolkit-modal + + Button b1; // in dlg1 + Button b2; // in dlg2 + + Robot r = null; + + volatile boolean b1pressed, b2pressed; + volatile boolean dlg1activated, dlg2activated; + volatile int b1Width, b1Height; + volatile int b2Width, b2Height; + volatile Point p1, p2; + + public static void main(String args[]) throws Exception { + BlockedMouseInputTest3 test = new BlockedMouseInputTest3(); + test.start(); + } + + public void start() throws Exception { + try { + r = new Robot(); + EventQueue.invokeAndWait(() -> { + frame = new Frame("Parent frame"); + frame.setBounds(0, 0, 200, 100); + frame.setVisible(true); + + // create d and set it visible + d = new Dialog(frame, "Toolkit-modal", Dialog.ModalityType.TOOLKIT_MODAL); + d.setBounds(250, 0, 200, 100); + }); + EventQueue.invokeLater(new Runnable() { + public void run() { + d.setVisible(true); + } + }); + + r.delay(1000); + r.waitForIdle(); + + // create dlg1 and set it visible + // dlg1 is blocked by d + + EventQueue.invokeAndWait(() -> { + dlg1 = new Dialog(frame, "Application-modal 1", Dialog.ModalityType.APPLICATION_MODAL); + dlg1.setBounds(0, 150, 200, 100); + dlg1.addWindowListener(new WindowAdapter() { + public void windowActivated(WindowEvent e) { + dlg1activated = true; + } + }); + b1 = new Button("B1"); + b1.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + b1pressed = true; + } + }); + dlg1.add(b1); + }); + EventQueue.invokeLater(new Runnable() { + public void run() { + dlg1.setVisible(true); + } + }); + + r.delay(1000); + r.waitForIdle(); + + // create dlg2 and set it visible + // dlg2 is blocked by d + EventQueue.invokeAndWait(() -> { + dlg2 = new Dialog(frame, "Application-modal 2", Dialog.ModalityType.APPLICATION_MODAL); + dlg2.setBounds(0, 300, 200, 100); + dlg2.addWindowListener(new WindowAdapter() { + public void windowActivated(WindowEvent e) { + dlg2activated = true; + } + }); + b2 = new Button("B2"); + b2.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + b2pressed = true; + } + }); + dlg2.add(b2); + }); + EventQueue.invokeLater(new Runnable() { + public void run() { + dlg2.setVisible(true); + } + }); + + r.delay(1000); + r.waitForIdle(); + + + // hide d + // dlg2 is unblocked and dlg1 is blocked by dlg2 + EventQueue.invokeAndWait(() -> { + d.setVisible(false); + }); + + r.delay(1000); + r.waitForIdle(); + + // values to check + b1pressed = false; + b2pressed = false; + dlg1activated = false; + dlg2activated = false; + System.err.println(KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow()); + + // check mouse events and activation + EventQueue.invokeAndWait(() -> { + p1 = b1.getLocationOnScreen(); + b1Width = b1.getWidth(); + b1Height = b1.getHeight(); + }); + clickPoint(r, p1.x + b1Width / 2, p1.y + b1Height / 2); + + EventQueue.invokeAndWait(() -> { + dlg1activated = (KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow() == dlg1); + }); + + EventQueue.invokeAndWait(() -> { + p2 = b2.getLocationOnScreen(); + b2Width = b2.getWidth(); + b2Height = b2.getHeight(); + }); + + clickPoint(r, p2.x + b2Width / 2, p2.y + b2Height / 2); + + EventQueue.invokeAndWait(() -> { + dlg2activated = (KeyboardFocusManager.getCurrentKeyboardFocusManager().getActiveWindow() == dlg2); + }); + + if (dlg1activated || b1pressed || !dlg2activated || !b2pressed) { + throw new RuntimeException("Test is FAILED"); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + if (dlg1 != null) { + dlg1.dispose(); + } + if (dlg2 != null) { + dlg2.dispose(); + } + if (d != null) { + d.dispose(); + } + }); + } + } + + private static void clickPoint(Robot r, int x, int y) { + r.mouseMove(x, y); + r.delay(500); + r.mousePress(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + } +} diff --git a/test/jdk/java/awt/Modal/ModalDialogCannotBeMadeNonModalTest.java b/test/jdk/java/awt/Modal/ModalDialogCannotBeMadeNonModalTest.java new file mode 100644 index 00000000000..a228f34e1af --- /dev/null +++ b/test/jdk/java/awt/Modal/ModalDialogCannotBeMadeNonModalTest.java @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2005, 2023, 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 4272629 + @summary Modal dialog cannot be made non-modal + @key headful + @run main ModalDialogCannotBeMadeNonModalTest +*/ + +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Dialog; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +public class ModalDialogCannotBeMadeNonModalTest { + Frame frame = null; + Button button = null; + Dialog dialog = null; + Robot r = null; + volatile Point loc = null; + + volatile private boolean buttonPressed = false; + + public static void main(String args[]) throws Exception { + ModalDialogCannotBeMadeNonModalTest test = new ModalDialogCannotBeMadeNonModalTest(); + test.start(); + } + + public void start() throws Exception { + try { + r = new Robot(); + EventQueue.invokeAndWait(() -> { + frame = new Frame("Parent frame"); + frame.setLayout(new BorderLayout()); + frame.setBounds(200, 200, 200, 200); + frame.setVisible(true); + + button = new Button("Trigger"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + buttonPressed = true; + } + }); + frame.add(button); + frame.setVisible(true); + + dialog = new Dialog(frame, "Dialog"); + dialog.setBounds(0, 0, 100, 100); + dialog.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent we) { + we.getWindow().setVisible(false); + } + }); + }); + + r.delay(500); + r.waitForIdle(); + EventQueue.invokeAndWait(() -> { + loc = button.getLocationOnScreen(); + }); + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + if (dialog != null) { + dialog.dispose(); + } + }); + } + + } + public void test() throws Exception { + + // 1-visibility, 2-modality + System.out.println("1 create visible, modal ... "); + EventQueue.invokeAndWait(() -> { + dialog.setModal(true); + setDialogVisible(true); + }); + r.delay(1000); + r.waitForIdle(); + + System.out.println("2 set non visible, modal ... "); + EventQueue.invokeAndWait(() -> { + dialog.setVisible(false); + dialog.setModal(false); + }); + r.delay(1000); + r.waitForIdle(); + + System.out.println("3 set visible, non modal ... "); + EventQueue.invokeAndWait(() -> { + setDialogVisible(true); + }); + r.delay(1000); + r.waitForIdle(); + + System.out.println("4 checking ... "); + check(); + r.delay(1000); + r.waitForIdle(); + System.out.println("5 exit "); + } + + public void check() throws Exception { + r.delay(500); + r.mouseMove(loc.x + button.getWidth()/2, loc.y + button.getHeight()/2); + r.delay(500); + r.mousePress(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + + if (!buttonPressed) { + throw new RuntimeException("Test failed"); + } + } + + public void setDialogVisible(boolean visibility) { + if (visibility) { + new Thread(new Runnable() { + public void run() { + dialog.setVisible(true); + } + }).start(); + } else { + dialog.setVisible(false); + } + } +} diff --git a/test/jdk/java/awt/Modal/NonModalDialogReceiveEventsAfterModalTest.java b/test/jdk/java/awt/Modal/NonModalDialogReceiveEventsAfterModalTest.java new file mode 100644 index 00000000000..668533b027a --- /dev/null +++ b/test/jdk/java/awt/Modal/NonModalDialogReceiveEventsAfterModalTest.java @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2005, 2023, 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 4256692 + @summary Showing a non modal dialog after a modal dialog allows both to receive events + @key headful + @run main NonModalDialogReceiveEventsAfterModalTest +*/ + +import java.awt.BorderLayout; +import java.awt.Dialog; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; + +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; + +public class NonModalDialogReceiveEventsAfterModalTest implements Runnable +{ + Frame modalParentFrame, nonModalParentFrame; + Dialog modalDialog, nonModalDialog; + + volatile public static boolean passed = true; + volatile public static String errorMessage = null; + + Robot r = null; + volatile Point loc = null; + + public static void main(String args[]) throws Exception { + NonModalDialogReceiveEventsAfterModalTest test = new NonModalDialogReceiveEventsAfterModalTest(); + test.start(); + } + + public void start() throws Exception { + + // create an independent top level frame to be the + // parent of the modal dialog and show it + try { + r = new Robot(); + EventQueue.invokeAndWait(() -> { + modalParentFrame = new Frame("Parent of modal dialog"); + modalParentFrame.setBounds(100, 100, 200, 200); + modalParentFrame.setLayout(new BorderLayout()); + modalParentFrame.setVisible(true); + + // create an independent top level frame to be the + // parent of the non-modal dialog and show it + nonModalParentFrame = new Frame("Parent of non-modal dialog"); + nonModalParentFrame.setBounds(400, 100, 200, 200); + nonModalParentFrame.setLayout(new BorderLayout()); + nonModalParentFrame.setVisible(true); + + // create the non-modal dialog and kick off a + // thread to show it in 1 second + nonModalDialog = new Dialog(nonModalParentFrame, "Non modal", false); + nonModalDialog.setBounds(400, 150, 100, 100); + nonModalDialog.addMouseMotionListener(new TestMouseMotionAdapter()); + nonModalDialog.addFocusListener(new TestFocusAdapter()); + new Thread(this).start(); + + // create the modal dialog and show it from this thread + modalDialog = new Dialog(modalParentFrame, "Modal", true); + modalDialog.setBounds(100, 400, 100, 100); + modalDialog.setVisible(true); + }); + } finally { + EventQueue.invokeAndWait(() -> { + if (modalParentFrame != null) { + modalParentFrame.dispose(); + } + if (nonModalParentFrame != null) { + nonModalParentFrame.dispose(); + } + if (modalDialog != null) { + modalDialog.dispose(); + } + if (nonModalDialog != null) { + nonModalDialog.dispose(); + } + }); + } + + } + + // This is the implementation of Runnable and is + // used to show the non-modal dialog in 1 second + public void run() { + r.delay(1000); + r.waitForIdle(); + //show the non modal dialog + nonModalDialog.setVisible(true); + + r.delay(1000); + r.waitForIdle(); + test(); + } + + private void test() { + + // mouse, focus, activate events triggering + r.delay(500); + loc = nonModalDialog.getLocationOnScreen(); + r.delay(500); + + r.mouseMove(loc.x + (int) (nonModalDialog.getWidth() / 2), loc.y + (int) (nonModalDialog.getHeight() / 2)); + r.delay(100); + r.mousePress(InputEvent.BUTTON1_DOWN_MASK); + r.delay(100); + r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + r.delay(100); + r.mouseMove(loc.x - 100, loc.y - 100); + + r.waitForIdle(); + + // dispose modal window in order to finish test + modalDialog.dispose(); + + // check test result + if (!passed) { + throw new RuntimeException("test failed: " + errorMessage); + } + } + + public static void testFailed(String message) { + passed = false; + errorMessage = message; + } +} + +class TestMouseMotionAdapter extends MouseMotionAdapter { + + public void mouseClicked(MouseEvent e){ + NonModalDialogReceiveEventsAfterModalTest.testFailed("mouseClicked"); + } + + public void mouseEntered(MouseEvent e){ + NonModalDialogReceiveEventsAfterModalTest.testFailed("mouseEntered"); + } + + public void mouseExited(MouseEvent e){ + NonModalDialogReceiveEventsAfterModalTest.testFailed("mouseExited"); + } + + public void mousePressed(MouseEvent e){ + NonModalDialogReceiveEventsAfterModalTest.testFailed("mousePressed"); + } + + public void mouseReleased(MouseEvent e){ + NonModalDialogReceiveEventsAfterModalTest.testFailed("mouseReleased"); + } +} + +class TestFocusAdapter extends FocusAdapter { + public void focusGained(FocusEvent e){ + NonModalDialogReceiveEventsAfterModalTest.testFailed("focusGained"); + } + + public void focusLost(FocusEvent e){ + NonModalDialogReceiveEventsAfterModalTest.testFailed("focusLost"); + } +} diff --git a/test/jdk/java/awt/Modal/ParentCatchupDraggingChildDialogTest.java b/test/jdk/java/awt/Modal/ParentCatchupDraggingChildDialogTest.java new file mode 100644 index 00000000000..b74538ca6ce --- /dev/null +++ b/test/jdk/java/awt/Modal/ParentCatchupDraggingChildDialogTest.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2005, 2023, 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 5083555 + @summary Parent Windows of mouse events catchup while dragging child dialog window + @key headful + @run main ParentCatchupDraggingChildDialogTest +*/ + +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.Robot; + +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; + +import javax.swing.JButton; +import javax.swing.JDialog; +import javax.swing.JFrame; + + +public class ParentCatchupDraggingChildDialogTest { + JFrame frame = null; + JDialog dialog = null; + DialogThread thread = null; + JButton trigger = new JButton("trigger"); + JButton show = new JButton("show"); + Robot r = null; + volatile Point locTrigger, locDialog; + + volatile boolean passed = true; + + public static void main(String args[]) throws Exception { + ParentCatchupDraggingChildDialogTest test = new ParentCatchupDraggingChildDialogTest(); + test.start(); + } + + public void start () throws Exception { + try { + EventQueue.invokeAndWait(() -> { + frame = new JFrame("Parent frame"); + frame.setBounds(20, 20, 300, 300); + frame.setLayout(new FlowLayout()); + frame.add(trigger); + frame.add(show); + frame.setVisible(true); + + dialog = new JDialog(frame, "Dialog", true); + dialog.setBounds(100, 100, 300, 300); + + trigger.addMouseListener(new MouseAdapter() { + public void mouseEntered(MouseEvent e) { + System.out.println("Trigger button event: " + e); + passed = false; + } + }); + }); + + thread = new DialogThread(dialog); + thread.start(); + + test(); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + if (dialog != null) { + dialog.dispose(); + } + }); + } + } + + /* Test scenario: + * 1) dragging mouse over the 'Trigger' button in order to be sure that the events don't occured for non modal window + * 2) checking + * 3) close dialog in order to finish test + */ + private void test() throws Exception { + try { + r = new Robot(); + } catch (Exception e) { + throw new RuntimeException(e); + } + + r.delay(500); + EventQueue.invokeAndWait(() -> { + locTrigger = trigger.getLocationOnScreen(); + }); + + r.delay(500); + EventQueue.invokeAndWait(() -> { + locDialog = dialog.getLocationOnScreen(); + }); + r.delay(500); + + r.mouseMove(locDialog.x + dialog.getWidth() / 2, locDialog.y + dialog.getHeight() / 2); + r.delay(500); + r.mousePress(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + r.mouseMove(locTrigger.x + trigger.getWidth() / 2, locTrigger.y + trigger.getHeight() / 2); + r.delay(500); + r.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + r.delay(500); + + if (!passed) { + throw new RuntimeException("Test failed. Triggering occured."); + } + + EventQueue.invokeAndWait(() -> { + dialog.dispose(); + }); + } +} + +class DialogThread extends Thread { + JDialog dialog = null; + + public DialogThread(JDialog dialog){ + this.dialog = dialog; + } + + public void run(){ + dialog.setVisible(true); + } +} diff --git a/test/jdk/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java b/test/jdk/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java index 29b90c9d430..3f8eeb17b38 100644 --- a/test/jdk/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java +++ b/test/jdk/java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -105,7 +105,7 @@ public void mouseReleased(MouseEvent e) { //XToolkit: extra buttons should report MOVED events only //WToolkit: extra buttons should report DRAGGED events only if (i > 2){ //extra buttons only - if (tk.equals("sun.awt.X11.XToolkit") || tk.equals("sun.awt.motif.MToolkit")) { + if (tk.equals("sun.awt.X11.XToolkit")) { if (!moved || dragged) { throw new RuntimeException("Test failed."+ tk +" Button = " +(i+1) + " moved = "+moved +" : dragged = " +dragged); } @@ -152,4 +152,3 @@ public static void dragMouse(int button, int x0, int y0, int x1, int y1){ } } - diff --git a/test/jdk/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java b/test/jdk/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java index 3ab3ba3ff87..ee83a328f0f 100644 --- a/test/jdk/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java +++ b/test/jdk/java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -57,7 +57,7 @@ public static void main(String []s){ //MouseInfo.getNumberOfButtons() reports two more buttons on XToolkit //as they reserved for wheel (both directions). - if (tk.equals("sun.awt.X11.XToolkit") || tk.equals("sun.awt.motif.MToolkit")) { + if (tk.equals("sun.awt.X11.XToolkit")) { buttonsNum = buttonsNum - 2; } System.out.println("Number Of Buttons = "+ buttonsNum); diff --git a/test/jdk/java/awt/Robot/ManualInstructions/ManualInstructions.java b/test/jdk/java/awt/Robot/ManualInstructions/ManualInstructions.java deleted file mode 100644 index df842ab841e..00000000000 --- a/test/jdk/java/awt/Robot/ManualInstructions/ManualInstructions.java +++ /dev/null @@ -1,328 +0,0 @@ -/* - * Copyright (c) 2008, 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. - */ - -/* - test %W% %E% %I%, %G% - @bug 6315717 - @summary manual control over the Robot - @author Andrei Dmitriev : area=awt.robot - @run applet/manual=yesno ManualInstructions.html -*/ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; -import java.util.Timer; -import java.util.TimerTask; - -public class ManualInstructions extends Applet -{ - final static long SEND_DELAY = 1000; - - public static void main(String s[]){ - ManualInstructions mi = new ManualInstructions(); - mi.init(); - mi.start(); - } - - static Robot robot; - Point mouseLocation; //where mouse should be pressed each time - Panel target = new Panel(); - Button pressOn = new Button("press on ..."); - Button releaseOn = new Button("release on ..."); - Button clickOn = new Button("click on ..."); - Choice buttonNumber = new Choice(); - - public void init() - { - try { - robot = new Robot(); - } catch (AWTException ex) { - ex.printStackTrace(); - throw new RuntimeException(ex); - } - this.setLayout (new BorderLayout ()); - - target.setBackground(Color.green); - target.setName("GreenBox");//for the ease of debug - target.setPreferredSize(new Dimension(100, 100)); - String toolkit = Toolkit.getDefaultToolkit().getClass().getName(); - - // on X systems two buttons are reserved for wheel though they are countable by MouseInfo. - int buttonsNumber = toolkit.equals("sun.awt.windows.WToolkit")?MouseInfo.getNumberOfButtons():MouseInfo.getNumberOfButtons()-2; - - for (int i = 0; i < 8; i++){ - buttonNumber.add("BUTTON"+(i+1)+"_MASK"); - } - - pressOn.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e){ - System.out.println("Now pressing : " + (buttonNumber.getSelectedIndex()+1)); - - Timer timer = new Timer(); - TimerTask robotInteraction = new TimerTask(){ - public void run(){ - robot.mouseMove(updateTargetLocation().x, updateTargetLocation().y); - robot.mousePress(getMask(buttonNumber.getSelectedIndex()+1)); - } - }; - timer.schedule(robotInteraction, SEND_DELAY); - } - }); - - releaseOn.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e){ - System.out.println("Now releasing : " + (buttonNumber.getSelectedIndex()+1)); - Timer timer = new Timer(); - TimerTask robotInteraction = new TimerTask(){ - public void run(){ - robot.mouseMove(updateTargetLocation().x, updateTargetLocation().y); - robot.mouseRelease(getMask(buttonNumber.getSelectedIndex()+1)); - } - }; - timer.schedule(robotInteraction, SEND_DELAY); - } - }); - - clickOn.addActionListener(new ActionListener(){ - public void actionPerformed(ActionEvent e){ - System.out.println("Now clicking : " + (buttonNumber.getSelectedIndex()+1)); - Timer timer = new Timer(); - TimerTask robotInteraction = new TimerTask(){ - public void run(){ - robot.mouseMove(updateTargetLocation().x, updateTargetLocation().y); - robot.mousePress(getMask(buttonNumber.getSelectedIndex()+1)); - robot.mouseRelease(getMask(buttonNumber.getSelectedIndex()+1)); - } - }; - timer.schedule(robotInteraction, SEND_DELAY); - } - - }); - target.addMouseListener(new MouseAdapter(){ - public void mousePressed(MouseEvent e){ - Sysout.println(""+e); - } - public void mouseReleased(MouseEvent e){ - Sysout.println(""+e); - } - public void mouseClicked(MouseEvent e){ - Sysout.println(""+e); - } - }); - - String[] instructions = - { - "Do provide an instruction to the robot by", - "choosing the button number to act and ", - "pressing appropriate java.awt.Button on the left.", - "Inspect an output in the TextArea below.", - "Please don't generate non-natural sequences like Release-Release, etc.", - "If you use keyboard be sure that you released the keyboard shortly.", - "If events are generated well press Pass, otherwise Fail." - }; - Sysout.createDialogWithInstructions( instructions ); - - }//End init() - - private int getMask(int button){ - return InputEvent.getMaskForButton(button); - - /* - //this only works for standard buttons and for old JDK builds - int mask = 0; - switch (button){ - case 1: { - mask = InputEvent.BUTTON1_MASK; - break; - } - case 2: { - mask = InputEvent.BUTTON2_MASK; - break; - } - case 3: { - mask = InputEvent.BUTTON3_MASK; - break; - } - } - return mask; - */ - } - - private Point updateTargetLocation() { - return new Point(target.getLocationOnScreen().x + target.getWidth()/2, target.getLocationOnScreen().y + target.getHeight()/2); - } - - public void start () - { - //Get things going. Request focus, set size, et cetera - setSize (200,200); - setVisible(true); - validate(); - Frame f = new Frame ("Set action for Robot here."); - f.setLayout(new FlowLayout()); - f.add(buttonNumber); - f.add(pressOn); - f.add(releaseOn); - f.add(clickOn); - f.add(target); - f.pack(); - f.setVisible(true); - }// start() -}// class - -/* Place other classes related to the test after this line */ - - -/**************************************************** - Standard Test Machinery - DO NOT modify anything below -- it's a standard - chunk of code whose purpose is to make user - interaction uniform, and thereby make it simpler - to read and understand someone else's test. - ****************************************************/ - -/** - This is part of the standard test machinery. - It creates a dialog (with the instructions), and is the interface - for sending text messages to the user. - To print the instructions, send an array of strings to Sysout.createDialog - WithInstructions method. Put one line of instructions per array entry. - To display a message for the tester to see, simply call Sysout.println - with the string to be displayed. - This mimics System.out.println but works within the test harness as well - as standalone. - */ - -class Sysout -{ - private static TestDialog dialog; - - public static void createDialogWithInstructions( String[] instructions ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - dialog.printInstructions( instructions ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void createDialog( ) - { - dialog = new TestDialog( new Frame(), "Instructions" ); - String[] defInstr = { "Instructions will appear here. ", "" } ; - dialog.printInstructions( defInstr ); - dialog.setVisible(true); - println( "Any messages for the tester will display here." ); - } - - public static void printInstructions( String[] instructions ) - { - dialog.printInstructions( instructions ); - } - - - public static void println( String messageIn ) - { - dialog.displayMessage( messageIn ); - } - -}// Sysout class - -/** - This is part of the standard test machinery. It provides a place for the - test instructions to be displayed, and a place for interactive messages - to the user to be displayed. - To have the test instructions displayed, see Sysout. - To have a message to the user be displayed, see Sysout. - Do not call anything in this dialog directly. - */ -class TestDialog extends Dialog -{ - - TextArea instructionsText; - TextArea messageText; - int maxStringLength = 120; - - //DO NOT call this directly, go through Sysout - public TestDialog( Frame frame, String name ) - { - super( frame, name ); - int scrollBoth = TextArea.SCROLLBARS_BOTH; - instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth ); - add( "North", instructionsText ); - - messageText = new TextArea( "", 5, maxStringLength, scrollBoth ); - add("Center", messageText); - - pack(); - - setVisible(true); - }// TestDialog() - - //DO NOT call this directly, go through Sysout - public void printInstructions( String[] instructions ) - { - //Clear out any current instructions - instructionsText.setText( "" ); - - //Go down array of instruction strings - - String printStr, remainingStr; - for( int i=0; i < instructions.length; i++ ) - { - //chop up each into pieces maxSringLength long - remainingStr = instructions[ i ]; - while( remainingStr.length() > 0 ) - { - //if longer than max then chop off first max chars to print - if( remainingStr.length() >= maxStringLength ) - { - //Try to chop on a word boundary - int posOfSpace = remainingStr. - lastIndexOf( ' ', maxStringLength - 1 ); - - if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1; - - printStr = remainingStr.substring( 0, posOfSpace + 1 ); - remainingStr = remainingStr.substring( posOfSpace + 1 ); - } - //else just print - else - { - printStr = remainingStr; - remainingStr = ""; - } - - instructionsText.append( printStr + "\n" ); - }// while - }// for - }//printInstructions() - - //DO NOT call this directly, go through Sysout - public void displayMessage( String messageIn ) - { - messageText.append( messageIn + "\n" ); - System.out.println(messageIn); - } - -}// TestDialog class diff --git a/test/jdk/java/awt/ScrollPane/ScrollPaneTest.java b/test/jdk/java/awt/ScrollPane/ScrollPaneTest.java new file mode 100644 index 00000000000..7b628d900a5 --- /dev/null +++ b/test/jdk/java/awt/ScrollPane/ScrollPaneTest.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 1998, 2023, 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.awt.BorderLayout; +import java.awt.Button; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.GridLayout; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.ScrollPane; +import java.awt.TextField; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; + +/* + * @test + * @bug 4124460 + * @key headful + * @summary Test for initializing a Motif peer component causes a crash. +*/ + +public class ScrollPaneTest { + private static volatile Point p1 = null; + private static volatile Point p2 = null; + private static Robot robot = null; + + private static Point getClickPoint(Component component) { + Point locationOnScreen = component.getLocationOnScreen(); + Dimension size = component.getSize(); + locationOnScreen.x += size.width / 2; + locationOnScreen.y += size.height / 2; + return locationOnScreen; + } + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(100); + + try { + doTest(); + } finally { + ScrollPaneTester.disposeAll(); + } + } + + private static void doTest() throws Exception { + EventQueue.invokeAndWait(ScrollPaneTester::initAndShowGui); + + robot.waitForIdle(); + robot.delay(1000); + + EventQueue.invokeAndWait(() -> { + p1 = getClickPoint(ScrollPaneTester.st1.buttonRight); + p2 = getClickPoint(ScrollPaneTester.st1.buttonSwap); + }); + + robot.mouseMove(p1.x, p1.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.mouseMove(p2.x, p2.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.delay(1000); + + EventQueue.invokeAndWait(() -> { + p1 = getClickPoint(ScrollPaneTester.st2.buttonRight); + p2 = getClickPoint(ScrollPaneTester.st2.buttonSwap); + }); + + robot.mouseMove(p1.x, p1.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.mouseMove(p2.x, p2.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } +} + +class ScrollPaneTester implements ActionListener { + static ScrollPaneTester st1, st2; + final Button buttonLeft, buttonRight, buttonQuit, buttonSwap; + protected ScrollPane sp; + protected Frame f; + + public static void initAndShowGui() { + ScrollPaneTester.st1 = new ScrollPaneTester(true); + ScrollPaneTester.st2 = new ScrollPaneTester(false); + } + + public ScrollPaneTester(boolean large) { + sp = new ScrollPane(ScrollPane.SCROLLBARS_NEVER); + + Panel p = new Panel(); + + if (large) { + p.setLayout(new GridLayout(10, 10)); + for (int i = 0; i < 10; i++) + for (int j = 0; j < 10; j++) { + TextField tf = new TextField("I am " + i + j); + tf.setSize(100, 20); + p.add(tf); + } + } else { + TextField tf = new TextField("Smallness:"); + tf.setSize(150, 50); + p.add(tf); + } + + sp.add(p); + + // Button panel + buttonLeft = new Button("Left"); + buttonLeft.addActionListener(this); + buttonQuit = new Button("Quit"); + buttonQuit.addActionListener(this); + buttonSwap = new Button("Swap"); + buttonSwap.addActionListener(this); + buttonRight = new Button("Right"); + buttonRight.addActionListener(this); + + Panel bp = new Panel(); + bp.add(buttonLeft); + bp.add(buttonSwap); + bp.add(buttonQuit); + bp.add(buttonRight); + + // Window w/ button panel and scrollpane + f = new Frame("ScrollPane Test " + (large ? "large" : "small")); + f.setLayout(new BorderLayout()); + f.add("South", bp); + f.add("Center", sp); + + if (large) { + f.setSize(300, 200); + f.setLocation(100, 100); + } else { + f.setSize(200, 100); + f.setLocation(500, 100); + } + + f.setVisible(true); + } + + public static void disposeAll() { + ScrollPaneTester.st1.f.dispose(); + ScrollPaneTester.st2.f.dispose(); + } + + public static void + swapPanels() { + ScrollPane sss = st1.sp; + + st1.f.add("Center", st2.sp); + st1.sp = st2.sp; + + st2.f.add("Center", sss); + st2.sp = sss; + } + + public void + actionPerformed(ActionEvent ev) { + Object s = ev.getSource(); + + if (s == buttonLeft) { + scroll(true); + } else if (s == buttonRight) { + scroll(false); + } else if (s == buttonSwap) { + swapPanels(); + } else if (s == buttonQuit) { + disposeAll(); + } + } + + private void + scroll(boolean scroll_left) { + Point p = sp.getScrollPosition(); + + if (scroll_left) + p.x = Math.max(0, p.x - 20); + else { + int cwidth = sp.getComponent(0).getSize().width; + p.x = Math.min(p.x + 20, cwidth); + } + + sp.setScrollPosition(p); + } +} diff --git a/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java b/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java index c8e4e602fda..0ba80c10e78 100644 --- a/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java +++ b/test/jdk/java/awt/SplashScreen/MultiResolutionSplash/MultiResolutionSplashTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -120,6 +120,7 @@ static void testSplash(ImageInfo test) throws Exception { static void testFocus() throws Exception { Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); robot.setAutoDelay(50); Frame frame = new Frame(); @@ -130,6 +131,7 @@ static void testFocus() throws Exception { frame.add(textField); frame.setVisible(true); robot.waitForIdle(); + robot.delay(1000); robot.keyPress(KeyEvent.VK_A); robot.keyRelease(KeyEvent.VK_A); diff --git a/test/jdk/java/awt/TextArea/Length.java b/test/jdk/java/awt/TextArea/Length.java new file mode 100644 index 00000000000..1ea99659383 --- /dev/null +++ b/test/jdk/java/awt/TextArea/Length.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 1999, 2023, 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.awt.EventQueue; +import java.awt.TextArea; + +/* + * @test + * @bug 4120876 + * @key headful + * @summary Ensure that getText can handle strings of various lengths, + * in particular strings longer than 255 characters + */ + +public class Length { + + public static void main(String[] args) throws Exception { + EventQueue.invokeAndWait(() -> { + TextArea ta = new TextArea(); + StringBuffer sb = new StringBuffer("x"); + + for (int i = 0; i < 14; i++) { + String s = sb.toString(); + check(ta, s.substring(1)); + check(ta, s); + check(ta, s + "y"); + sb.append(s); + } + }); + } + + static void check(TextArea ta, String s) { + ta.setText(s); + String s2 = ta.getText(); + System.err.println(s.length() + " " + s2.length()); + if (s.length() != s2.length()) { + throw new RuntimeException("Expected " + s.length() + + "chars, got " + s2.length()); + } + } +} diff --git a/test/jdk/java/awt/TextComponent/CorrectSetCaretPositionDuringInitPeerTest.java b/test/jdk/java/awt/TextComponent/CorrectSetCaretPositionDuringInitPeerTest.java new file mode 100644 index 00000000000..6c288245df6 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/CorrectSetCaretPositionDuringInitPeerTest.java @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2005, 2023, 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 5100200 + @summary IAE in X11 text field peer code + @key headful +*/ + +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.TextField; + +public class CorrectSetCaretPositionDuringInitPeerTest +{ + static TextField tf; + static Frame frame; + + public static void main(String[] args) throws Exception { + try{ + EventQueue.invokeAndWait(() -> { + frame = new Frame("Caret Position test"); + tf = new TextField("Very very very long string"); + tf.setSelectionStart(10); + tf.setText("Short"); // now TextField.length() less than 10 + frame.add(tf); + + frame.pack(); + frame.setVisible(true); + }); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/TextComponent/DeselectionDuringDoSelectionNonVisibleTest.java b/test/jdk/java/awt/TextComponent/DeselectionDuringDoSelectionNonVisibleTest.java new file mode 100644 index 00000000000..bcd04e1bbfa --- /dev/null +++ b/test/jdk/java/awt/TextComponent/DeselectionDuringDoSelectionNonVisibleTest.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2005, 2023, 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 5100950 8199723 + @summary textarea.getSelectedText() returns the de-selected text, on XToolkit + @key headful + @requires (os.family == "mac") | (os.family == "windows") +*/ + +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.KeyboardFocusManager; +import java.awt.TextField; + +public class DeselectionDuringDoSelectionNonVisibleTest { + static TextField tf1; + static TextField tf2; + static Frame frame; + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(() -> { + frame = new Frame("Deselection test"); + tf1 = new TextField("Text Field 1"); + tf2 = new TextField("Text Field 2"); + frame.add(tf1); + frame.add(tf2); + frame.setLayout(new FlowLayout()); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.pack(); + frame.setVisible(true); + }); + + boolean isWin = System.getProperty("os.name").startsWith("Win"); + System.out.println("is Windows OS? " + isWin); + + Thread.sleep(500); + tf1.requestFocus(); + + Thread.sleep(500); + if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != tf1) { + throw new RuntimeException("Test failed (TextField1 isn't focus owner)."); + } + tf1.selectAll(); + Thread.sleep(500); + + tf2.requestFocus(); + Thread.sleep(500); + + if (KeyboardFocusManager.getCurrentKeyboardFocusManager().getFocusOwner() != tf2) { + throw new RuntimeException("Test failed (TextField2 isn't focus owner)."); + } + tf2.selectAll(); + Thread.sleep(500); + + String selectedText = tf1.getSelectedText(); + String text = tf1.getText(); + + System.out.println("tf1.getText()=" + text); + System.out.println("tf1.getSelectedText()=" + selectedText); + + // Motif behaviour: After the selection of the second text, the first selected + // text is unselected + if (!selectedText.equals("") && !isWin) { + throw new RuntimeException("Test failed (TextField1 isn't deselected)."); + } + + // Windows behaviour: After the selection of the second text, the first selected + // text is only not highlighted + if (!selectedText.equals(text) && isWin) { + throw new RuntimeException("Test failed (TextField1 is deselected)."); + } + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/java/awt/TextComponent/GetCaretPosOutOfBoundsTest.java b/test/jdk/java/awt/TextComponent/GetCaretPosOutOfBoundsTest.java new file mode 100644 index 00000000000..01ba3fd1ba7 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/GetCaretPosOutOfBoundsTest.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2006, 2023, 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 4995931 + @summary java.awt.TextComponent caret position should be within the text bounds + @key headful +*/ + +import java.awt.EventQueue; +import java.awt.TextField; + +public class GetCaretPosOutOfBoundsTest { + static TextField tf; + public static void main(String[] args) throws Exception { + EventQueue.invokeAndWait(() -> { + tf = new TextField("1234567890"); + tf.setCaretPosition(100); + int pos = tf.getCaretPosition(); + if (pos > 10) { + throw new RuntimeException("Wrong caret position:" + pos + " instead of 10"); + } + tf.setText("12345"); + if (tf.getCaretPosition() > 5) { + throw new RuntimeException("Wrong caret position:" + pos + " instead of 5"); + } + }); + } +} diff --git a/test/jdk/java/awt/TextComponent/InitialInsertionCaretPositionTest.java b/test/jdk/java/awt/TextComponent/InitialInsertionCaretPositionTest.java new file mode 100644 index 00000000000..c5c27f3519b --- /dev/null +++ b/test/jdk/java/awt/TextComponent/InitialInsertionCaretPositionTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 1999, 2023, 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 4185654 + @summary tests that the text insertion caret is positioned before the first character + @key headful +*/ + +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.TextField; +import java.awt.TextArea; + +public class InitialInsertionCaretPositionTest { + static TextField textField; + static TextArea textArea; + static String failureMessage = ""; + + public static void main(String[] args) throws Exception { + EventQueue.invokeAndWait(() -> { + textArea = new TextArea("abcdefghij\nabcdefghij"); + textField = new TextField("abcdefghij"); + + boolean textFieldPassed = (textField.getCaretPosition() == 0); + boolean textAreaPassed = (textArea.getCaretPosition() == 0); + + if (!textFieldPassed) { + failureMessage += " The text insertion caret for the text field is not\n"; + failureMessage += " initially set before the first character.\n"; + } + if (!textAreaPassed) { + failureMessage += " The text insertion caret for the text area is not\n"; + failureMessage += " initially set before the first character.\n"; + } + if (textAreaPassed && textFieldPassed) { + System.out.println("The test passed."); + } else { + System.out.println("The test failed:"); + System.out.println(failureMessage); + } + if (!textAreaPassed || !textFieldPassed) { + throw new RuntimeException(failureMessage); + } + }); + } +} diff --git a/test/jdk/java/awt/TextComponent/MiddleMouseClickPasteTest.java b/test/jdk/java/awt/TextComponent/MiddleMouseClickPasteTest.java new file mode 100644 index 00000000000..f317c023bb1 --- /dev/null +++ b/test/jdk/java/awt/TextComponent/MiddleMouseClickPasteTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2001, 2023, 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 4426750 + @requires (os.family == "linux") + @key headful + @summary tests that middle mouse button click pastes primary selection +*/ + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.TextComponent; +import java.awt.TextField; + +import java.awt.datatransfer.Clipboard; +import java.awt.datatransfer.StringSelection; +import java.awt.event.InputEvent; +import java.awt.Toolkit; + +public class MiddleMouseClickPasteTest { + static final int FRAME_ACTIVATION_TIMEOUT = 1000; + static final int SELECTION_PASTE_TIMEOUT = 1000; + static final int CLICK_INTERVAL = 50; + static final String TEST_TEXT = "TEST TEXT"; + static Frame frame; + static TextField tf; + static TextArea ta; + static final Clipboard systemSelection = Toolkit.getDefaultToolkit().getSystemSelection(); + + + public static void main(String[] args) throws Exception { + if (systemSelection != null) { + try { + EventQueue.invokeAndWait(MiddleMouseClickPasteTest::createAndShowGui); + Thread.sleep(FRAME_ACTIVATION_TIMEOUT); + + checkPaste(tf); + checkPaste(ta); + } catch (Exception e) { + throw new RuntimeException(e); + } finally { + EventQueue.invokeAndWait(()-> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + } + + public static void createAndShowGui() { + frame = new Frame(); + tf = new TextField(); + ta = new TextArea(); + + frame.setLayout(new BorderLayout()); + frame.add(tf, BorderLayout.NORTH); + frame.add(ta, BorderLayout.CENTER); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void checkPaste(TextComponent textComponent) throws Exception { + + final Point sourcePoint = textComponent.getLocationOnScreen(); + final Dimension d = textComponent.getSize(); + sourcePoint.translate(d.width / 2, d.height / 2); + final Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(CLICK_INTERVAL); + + textComponent.setText(""); + systemSelection.setContents(new StringSelection(TEST_TEXT), null); + + robot.mouseMove(sourcePoint.x, sourcePoint.y); + robot.mousePress(InputEvent.BUTTON2_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON2_DOWN_MASK); + robot.delay(SELECTION_PASTE_TIMEOUT); + + if (!TEST_TEXT.equals(textComponent.getText())) { + throw new RuntimeException("Primary selection not pasted" + + " into: " + textComponent); + } + } +} diff --git a/test/jdk/java/awt/Window/FindOwner/FindOwnerTest.html b/test/jdk/java/awt/Window/FindOwner/FindOwnerTest.html deleted file mode 100644 index 38846d9285f..00000000000 --- a/test/jdk/java/awt/Window/FindOwner/FindOwnerTest.html +++ /dev/null @@ -1,44 +0,0 @@ - - - - - Testing Menus - - - - - - diff --git a/test/jdk/java/awt/Window/FindOwner/FindOwnerTest.java b/test/jdk/java/awt/Window/FindOwner/FindOwnerTest.java deleted file mode 100644 index 0d4f0ccd60e..00000000000 --- a/test/jdk/java/awt/Window/FindOwner/FindOwnerTest.java +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2015, 2016, 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. - */ - -/* @bug 8139227 - @summary Text fields in JPopupMenu structure do not receive focus in hosted - Applets - @author Semyon Sadetsky -*/ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; - -public class FindOwnerTest extends Applet -{ - - private boolean gained; - - public void init() { - super.init(); - } - - @Override - public void start() { - Window owner = SwingUtilities.windowForComponent(this); - - Window window1 = new Window(owner); - window1.setVisible(true); - - Window window2 = new Window(window1); - window2.setFocusable(true); - JTextField field = new JTextField("JTextField"); - field.addFocusListener(new FocusListener() { - @Override - public void focusGained(FocusEvent e) { - gained = true; - } - - @Override - public void focusLost(FocusEvent e) { - } - }); - window2.setBounds(100, 100, 200, 200); - window2.add(field); - window2.setVisible(true); - - try { - gained = false; - Robot robot = new Robot(); - robot.setAutoDelay(50); - robot.waitForIdle(); - robot.delay(200); - - Point p = field.getLocationOnScreen(); - System.out.println(p); - robot.mouseMove(p.x + 1, p.y + 1); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.mouseRelease(InputEvent.BUTTON1_MASK); - robot.waitForIdle(); - robot.delay(200); - - if (!gained) { - throw new Exception("Focus is not gained upon mouse click"); - } - System.out.println("ok"); - } catch (SecurityException e) { - - JOptionPane optionPane = new JOptionPane( - "You are in the browser so test is manual. Try to " + - "click \"JTextField\" in the opened window then press OK " + - "below", - JOptionPane.PLAIN_MESSAGE, JOptionPane.OK_CANCEL_OPTION); - JDialog dialog = - optionPane.createDialog(null,"FindOwnerTest instruction"); - dialog.setModalityType(Dialog.ModalityType.DOCUMENT_MODAL); - dialog.setVisible(true); - if (!gained) { - throw new RuntimeException( - "Focus is not gained upon mouse click"); - } - System.out.println("ok"); - } catch (Exception e) { - throw new RuntimeException(e); - } finally { - window1.dispose(); - stop(); - } - } -} diff --git a/test/jdk/java/awt/Window/Grab/GrabTest.java b/test/jdk/java/awt/Window/Grab/GrabTest.java index 5db28cb15b5..b173477c164 100644 --- a/test/jdk/java/awt/Window/Grab/GrabTest.java +++ b/test/jdk/java/awt/Window/Grab/GrabTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2023, 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 @@ -22,19 +22,34 @@ */ /* - @test - @key headful - @bug 7124430 - @summary Tests that SunToolkit.grab API works - @author anton.tarasov@oracle.com: area=awt.toolkit - @library ../../regtesthelpers - @modules java.desktop/sun.awt - @build Util - @run main GrabTest -*/ - -import java.awt.*; -import java.awt.event.*; + * @test + * @key headful + * @bug 7124430 + * @summary Tests that SunToolkit.grab API works + * @library ../../regtesthelpers + * @modules java.desktop/sun.awt + * @build Util + * @run main GrabTest + */ + + +import java.awt.AWTEvent; +import java.awt.Button; +import java.awt.Color; +import java.awt.FlowLayout; +import java.awt.Point; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.Window; +import java.awt.event.AWTEventListener; +import java.awt.event.MouseAdapter; + +import javax.swing.SwingUtilities; import test.java.awt.regtesthelpers.Util; public class GrabTest { @@ -56,9 +71,13 @@ public class GrabTest { static volatile boolean passed = true; - public static void main(String[] args) { + public static void main(String[] args) throws Exception { + + robot = new Robot(); + robot.setAutoDelay(100); - Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { + SwingUtilities.invokeAndWait(() -> { + Toolkit.getDefaultToolkit().addAWTEventListener(new AWTEventListener() { public void eventDispatched(AWTEvent e) { System.out.println(e); if (e instanceof sun.awt.UngrabEvent) { @@ -67,61 +86,56 @@ public void eventDispatched(AWTEvent e) { } }, sun.awt.SunToolkit.GRAB_EVENT_MASK); - f = new Frame("Frame"); - f.setBounds(0, 0, 300, 300); - f.addMouseListener(new MouseAdapter() { + f = new Frame("Frame"); + f.setBounds(0, 0, 300, 300); + f.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { System.out.println(e); framePressed = true; } }); - f1 = new Frame("OtherFrame"); - f1.setBounds(700, 100, 300, 300); + f1 = new Frame("OtherFrame"); + f1.setBounds(700, 100, 300, 300); - w = new Window(f); - w.setLayout(new FlowLayout()); - b = new Button("Press"); - b.addActionListener(new ActionListener() { + w = new Window(f); + w.setLayout(new FlowLayout()); + b = new Button("Press"); + b.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { System.out.println(e); buttonPressed = true; } }); - w.add(b); - w.setBounds(400, 100, 300, 300); - w.setBackground(Color.blue); - w.addMouseListener(new MouseAdapter() { + w.add(b); + w.setBounds(400, 100, 300, 300); + w.setBackground(Color.blue); + w.addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent e) { System.out.println(e); windowPressed = true; } }); - f.setVisible(true); - w.setVisible(true); + f.setVisible(true); + w.setVisible(true); - frame = new Frame(); - window1 = new Window(frame); - window1.setSize(200, 200); - window1.setLocationRelativeTo(null); - window1.setBackground(Color.blue); + frame = new Frame(); + window1 = new Window(frame); + window1.setSize(200, 200); + window1.setLocationRelativeTo(null); + window1.setBackground(Color.blue); - window2 = new Window(window1); - window2.setSize(100, 100); - window2.setLocationRelativeTo(null); - window2.setBackground(Color.green); + window2 = new Window(window1); + window2.setSize(100, 100); + window2.setLocationRelativeTo(null); + window2.setBackground(Color.green); - tk = (sun.awt.SunToolkit)Toolkit.getDefaultToolkit(); - - try { - robot = new Robot(); - } catch (AWTException ex) { - throw new RuntimeException(ex); - } + tk = (sun.awt.SunToolkit)Toolkit.getDefaultToolkit(); + }); Util.waitForIdle(robot); - + robot.delay(500); test(); } @@ -131,6 +145,7 @@ public static void test() { // 1. Check that button press doesn't cause ungrab Util.clickOnComp(b, robot); Util.waitForIdle(robot); + checkAndThrow(buttonPressed, "Error: Button can not be pressed"); if (ungrabbed) { passed = false; @@ -151,6 +166,7 @@ public static void test() { // 3. Check that press on the frame causes ungrab, event must be dispatched Util.clickOnComp(f, robot); Util.waitForIdle(robot); + checkAndThrow(framePressed, "Error: Frame can't be pressed"); if (!ungrabbed) { passed = false; @@ -173,28 +189,33 @@ public static void test() { // 5. Check that press on the other frame's title causes ungrab f1.setVisible(true); Util.waitForIdle(robot); + robot.delay(500); + Util.clickOnTitle(f1, robot); + Util.waitForIdle(robot); + if (!ungrabbed) { passed = false; System.err.println("Failure: [5] Press inside of other Frame's title didn't cause ungrab"); } f.requestFocus(); // restore focus Util.waitForIdle(robot); + if (!f.hasFocus()) { System.err.println("Error: Frame can't be focused"); } ungrabbed = false; tk.grab(w); - // 6. Check that press on the outside area causes ungrab Point loc = f.getLocationOnScreen(); robot.mouseMove(loc.x + 100, loc.y + f.getSize().height + 10); Util.waitForIdle(robot); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.delay(50); - robot.mouseRelease(InputEvent.BUTTON1_MASK); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); Util.waitForIdle(robot); + if (!ungrabbed) { passed = false; System.err.println("Failure: [6] Press on the outside area didn't cause ungrab"); @@ -218,6 +239,7 @@ public static void test() { window1.setVisible(true); window2.setVisible(true); Util.waitForIdle(robot); + robot.delay(500); tk.grab(window1); diff --git a/test/jdk/java/awt/Window/GrabSequence/GrabSequence.java b/test/jdk/java/awt/Window/GrabSequence/GrabSequence.java index 686cae28010..da419e10ef1 100644 --- a/test/jdk/java/awt/Window/GrabSequence/GrabSequence.java +++ b/test/jdk/java/awt/Window/GrabSequence/GrabSequence.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,11 +40,6 @@ public class GrabSequence { private static void init() { - String toolkit = Toolkit.getDefaultToolkit().getClass().getName(); - if ( toolkit.equals("sun.awt.motif.MToolkit")){ - System.out.println("This test is for XToolkit and WToolkit only. Now using " + toolkit + ". Automatically passed."); - return; - } Frame frame = new Frame("Frame"); frame.setBackground(Color.green); frame.setForeground(Color.green); diff --git a/test/jdk/java/awt/Window/WindowOwner.java b/test/jdk/java/awt/Window/WindowOwner.java new file mode 100644 index 00000000000..82cb35a1faa --- /dev/null +++ b/test/jdk/java/awt/Window/WindowOwner.java @@ -0,0 +1,155 @@ +/* + * Copyright (c) 1998, 2023, 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.awt.Dialog; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Panel; +import java.awt.Window; +import java.util.ArrayList; +import java.util.List; + +/* + * @test + * @key headful + * @summary automated test for window-ownership on Windows, Frames, and Dialogs + */ + +public class WindowOwner extends Panel { + + Label status = null; + static List windowsToDispose = new ArrayList<>(); + + public static void main(String[] args) throws Exception { + WindowOwner windowOwner = new WindowOwner(); + try { + EventQueue.invokeAndWait(windowOwner::init); + Thread.sleep(2000); + } finally { + EventQueue.invokeAndWait( + () -> windowsToDispose.forEach(Window::dispose) + ); + } + } + + public void init() { + status = new Label(); + add(status); + + statusMessage("Testing Window Ownership..."); + + // Test Frame as owner + Frame frame0 = new Frame("WindowOwner Test"); + windowsToDispose.add(frame0); + frame0.add("Center", new Label("Frame Level0")); + + Dialog dialog1 = new Dialog(frame0, "WindowOwner Test"); + windowsToDispose.add(dialog1); + dialog1.add("Center", new Label("Dialog Level1")); + verifyOwner(dialog1, frame0); + + Window window1 = new Window(frame0); + windowsToDispose.add(window1); + window1.add("Center", new Label("Window Level1")); + window1.setBounds(10, 10, 140, 70); + verifyOwner(window1, frame0); + + verifyOwnee(frame0, dialog1); + verifyOwnee(frame0, window1); + + // Test Dialog as owner + Dialog dialog2 = new Dialog(dialog1, "WindowOwner Test"); + windowsToDispose.add(dialog2); + dialog2.add("Center", new Label("Dialog Level2")); + verifyOwner(dialog2, dialog1); + + Window window2 = new Window(dialog1); + windowsToDispose.add(window2); + window2.add("Center", new Label("Window Level2")); + window2.setBounds(110, 110, 140, 70); + verifyOwner(window2, dialog1); + + verifyOwnee(dialog1, window2); + verifyOwnee(dialog1, dialog2); + + // Test Window as owner + Window window3 = new Window(window2); + windowsToDispose.add(window3); + window3.add("Center", new Label("Window Level3")); + window3.setBounds(210, 210, 140, 70); + verifyOwner(window3, window2); + verifyOwnee(window2, window3); + + // Ensure native peers handle ownership without errors + frame0.pack(); + frame0.setVisible(true); + + dialog1.pack(); + dialog1.setVisible(true); + + window1.setLocation(50, 50); + window1.setVisible(true); + + dialog2.pack(); + dialog2.setVisible(true); + + window2.setLocation(100, 100); + window2.setVisible(true); + + window3.setLocation(150, 150); + window3.setVisible(true); + + statusMessage("Window Ownership test completed successfully."); + } + + public void statusMessage(String msg) { + status.setText(msg); + status.invalidate(); + validate(); + } + + public static void verifyOwner(Window ownee, Window owner) { + if (ownee.getOwner() != owner) { + throw new RuntimeException("Window owner not valid for " + + ownee.getName()); + } + } + + public static void verifyOwnee(Window owner, Window ownee) { + Window[] ownedWins = owner.getOwnedWindows(); + if (!windowInList(ownedWins, ownee)) { + throw new RuntimeException("Ownee " + ownee.getName() + + " not found in owner list for " + owner.getName()); + } + } + + public static boolean windowInList(Window[] windows, Window target) { + for (Window window : windows) { + if (window == target) { + return true; + } + } + return false; + } +} diff --git a/test/jdk/java/awt/color/ICC_Profile/CustomCMMID.java b/test/jdk/java/awt/color/ICC_Profile/CustomCMMID.java new file mode 100644 index 00000000000..5eb6221d39e --- /dev/null +++ b/test/jdk/java/awt/color/ICC_Profile/CustomCMMID.java @@ -0,0 +1,69 @@ +/* + * Copyright Amazon.com Inc. 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.awt.color.ColorSpace; +import java.awt.color.ICC_Profile; +import java.util.Arrays; + +/** + * @test + * @bug 8321489 + * @summary tests that the cmm id is not ignored + */ +public final class CustomCMMID { + + private static final byte[] JAVA_ID = { + (byte) 'j', (byte) 'a', (byte) 'v', (byte) 'a', + }; + + private static final int[] CS = { + ColorSpace.CS_CIEXYZ, ColorSpace.CS_GRAY, ColorSpace.CS_LINEAR_RGB, + ColorSpace.CS_PYCC, ColorSpace.CS_sRGB + }; + + public static void main(String[] args) { + for (int cs : CS) { + ICC_Profile p = createProfile(cs); + validate(p); + } + } + + private static ICC_Profile createProfile(int type) { + byte[] data = ICC_Profile.getInstance(type).getData(); + System.arraycopy(JAVA_ID, 0, data, ICC_Profile.icHdrCmmId, + JAVA_ID.length); + return ICC_Profile.getInstance(data); + } + + private static void validate(ICC_Profile p) { + byte[] header = p.getData(ICC_Profile.icSigHead); + byte[] id = new byte[JAVA_ID.length]; + System.arraycopy(header, ICC_Profile.icHdrCmmId, id, 0, JAVA_ID.length); + + if (!java.util.Arrays.equals(id, JAVA_ID)) { + System.err.println("Expected: " + Arrays.toString(JAVA_ID)); + System.err.println("Actual: " + Arrays.toString(id)); + throw new RuntimeException("Wrong cmm id"); + } + } +} diff --git a/test/jdk/java/awt/datatransfer/MimeFormatsTest.java b/test/jdk/java/awt/datatransfer/MimeFormatsTest.java index a22cc47877d..6f4f1e592de 100644 --- a/test/jdk/java/awt/datatransfer/MimeFormatsTest.java +++ b/test/jdk/java/awt/datatransfer/MimeFormatsTest.java @@ -103,7 +103,7 @@ public void childRun() { ClipboardOwner owner = new ClipboardOwner() { public void lostOwnership(Clipboard clipboard, Transferable contents) { - System.err.println("%d exit".formatted( + System.err.println(String.format("%d exit", System.currentTimeMillis())); System.err.println("Exiting"); System.exit(0); @@ -115,7 +115,7 @@ public void lostOwnership(Clipboard clipboard, synchronized (lock) { // Wait to let the parent retrieve the contents. try { - System.err.println("%d wait".formatted( + System.err.println(String.format("%d wait", System.currentTimeMillis())); lock.wait(); } catch (InterruptedException e) { diff --git a/test/jdk/java/awt/dnd/MouseEventAfterStartDragTest/MouseEventAfterStartDragTest.java b/test/jdk/java/awt/dnd/MouseEventAfterStartDragTest/MouseEventAfterStartDragTest.java new file mode 100644 index 00000000000..faa98c43b75 --- /dev/null +++ b/test/jdk/java/awt/dnd/MouseEventAfterStartDragTest/MouseEventAfterStartDragTest.java @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2014, 2024, 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.awt.AWTEvent; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.event.AWTEventListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseMotionAdapter; +import java.awt.event.MouseMotionListener; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4613903 + * @summary verifies that mouse events are not dispatched during drag + * @key headful + * @run main MouseEventAfterStartDragTest + */ + +public final class MouseEventAfterStartDragTest implements AWTEventListener { + final Frame frame = new Frame(); + volatile Point srcPoint; + volatile Dimension d; + volatile MouseEvent lastMouseEvent = null; + volatile boolean passed = true; + final DragSource dragSource = DragSource.getDefaultDragSource(); + final Transferable transferable = new StringSelection("TEXT"); + + final MouseMotionListener mouseMotionListener = new MouseMotionAdapter() { + public void mouseDragged(MouseEvent e) { + System.out.println("mouseDragged: " + e + + ", hash:" + e.hashCode()); + if (lastMouseEvent != null && !e.equals(lastMouseEvent)) { + System.out.println("Unexpected: " + e + + ", hash:" + e.hashCode()); + passed = false; + } + } + }; + + final DragSourceListener dragSourceListener = new DragSourceAdapter() { + public void dragDropEnd(DragSourceDragEvent dsde) { + System.out.println("dragDropEnd: " + dsde); + lastMouseEvent = null; + } + }; + + final DragGestureListener dragGestureListener = new DragGestureListener() { + public void dragGestureRecognized(DragGestureEvent dge) { + System.out.println("dragGestureRecognized: " + dge); + Object[] events = dge.toArray(); + Object lastEvent = events[events.length - 1]; + if (lastEvent instanceof MouseEvent) { + lastMouseEvent = (MouseEvent) lastEvent; + } + System.out.println("The last mouse event: " + lastMouseEvent + + ", hash:" + lastMouseEvent.hashCode()); + dge.startDrag(null, transferable, dragSourceListener); + } + }; + + static final Object SYNC_LOCK = new Object(); + static final int MOUSE_RELEASE_TIMEOUT = 1000; + volatile Component clickedComponent = null; + + public static void main(String[] args) throws Exception { + System.setProperty("awt.dnd.drag.threshold", "0"); + MouseEventAfterStartDragTest app = new MouseEventAfterStartDragTest(); + try { + app.createAndShowGUI(); + app.test(); + } finally { + app.dispose(); + } + } + + public void createAndShowGUI() throws Exception { + SwingUtilities.invokeAndWait(() -> { + frame.setTitle("Test frame"); + frame.setBounds(100, 100, 200, 200); + frame.setLocationRelativeTo(null); + frame.addMouseMotionListener(mouseMotionListener); + dragSource.createDefaultDragGestureRecognizer(frame, DnDConstants.ACTION_COPY_OR_MOVE, + dragGestureListener); + + frame.getToolkit().addAWTEventListener(this, AWTEvent.MOUSE_EVENT_MASK); + frame.setVisible(true); + }); + } + + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } + + public void test() throws Exception { + final Robot robot = new Robot(); + robot.setAutoDelay(45); + robot.waitForIdle(); + + SwingUtilities.invokeAndWait(() -> { + srcPoint = frame.getLocationOnScreen(); + d = frame.getSize(); + }); + srcPoint.translate(d.width / 2, d.height / 2); + + if (!pointInComponent(robot, srcPoint, frame)) { + System.err.println("WARNING: Couldn't locate source frame."); + return; + } + + final Point dstPoint = new Point(srcPoint); + dstPoint.translate(d.width / 4, d.height / 4); + + if (!pointInComponent(robot, dstPoint, frame)) { + System.err.println("WARNING: Couldn't locate target frame."); + return; + } + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseMove(srcPoint.x, srcPoint.y); + robot.delay(250); + System.out.println("srcPoint = " + srcPoint); + for (; !srcPoint.equals(dstPoint); + srcPoint.translate(sign(dstPoint.x - srcPoint.x), + sign(dstPoint.y - srcPoint.y))) { + robot.mouseMove(srcPoint.x, srcPoint.y); + System.out.println("srcPoint = " + srcPoint); + } + + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + System.out.println("done"); + robot.waitForIdle(); + robot.delay(MOUSE_RELEASE_TIMEOUT); + + if (!passed) { + throw new RuntimeException("Test failed"); + } + } + + public void dispose() throws Exception { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + public void reset() { + clickedComponent = null; + } + + public void eventDispatched(AWTEvent e) { + if (e.getID() == MouseEvent.MOUSE_RELEASED) { + clickedComponent = (Component) e.getSource(); + synchronized (SYNC_LOCK) { + SYNC_LOCK.notifyAll(); + } + } + } + + boolean pointInComponent(Robot robot, Point p, Component comp) + throws InterruptedException { + robot.waitForIdle(); + reset(); + robot.mouseMove(p.x, p.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + synchronized (SYNC_LOCK) { + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT); + } + + Component c = clickedComponent; + + while (c != null && c != comp) { + c = c.getParent(); + } + + return c == comp; + } +} diff --git a/test/jdk/java/awt/dnd/RejectDragDropActionTest.java b/test/jdk/java/awt/dnd/RejectDragDropActionTest.java new file mode 100644 index 00000000000..f8d53ac45bf --- /dev/null +++ b/test/jdk/java/awt/dnd/RejectDragDropActionTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2003, 2023, 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 4774532 + @summary tests that DropTargetDragEvent.getDropAction() returns correct value + after DropTargetDragEvent.rejectDrag() + @key headful + @run main RejectDragDropActionTest +*/ + +import java.awt.AWTException; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.datatransfer.StringSelection; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragGestureRecognizer; +import java.awt.dnd.DragSource; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetAdapter; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.InputEvent; +import java.lang.reflect.InvocationTargetException; + + +public class RejectDragDropActionTest { + + private static volatile boolean incorrectActionDetected = false; + + private static final int FRAME_ACTIVATION_TIMEOUT = 3000; + + private static Frame frame; + private static DragSource ds; + private static DragGestureListener dgl; + private static DragGestureRecognizer dgr; + private final DropTargetListener dtl = new DropTargetAdapter() { + public void dragEnter(DropTargetDragEvent dtde) { + dtde.rejectDrag(); + } + public void dragOver(DropTargetDragEvent dtde) { + if (dtde.getDropAction() == DnDConstants.ACTION_NONE) { + incorrectActionDetected = true; + } + } + public void drop(DropTargetDropEvent dtde) { + dtde.rejectDrop(); + } + }; + private final DropTarget dt = new DropTarget(frame, dtl); + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + EventQueue.invokeAndWait(() -> { + frame = new Frame("RejectDragDropActionTest"); + ds = DragSource.getDefaultDragSource(); + dgl = dge -> dge.startDrag(null, new StringSelection("OOKK")); + dgr = ds.createDefaultDragGestureRecognizer(frame, DnDConstants.ACTION_COPY, dgl); + frame.setBounds(100, 100, 200, 200); + frame.setVisible(true); + }); + + try { + Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(FRAME_ACTIVATION_TIMEOUT); + + Point startPoint = frame.getLocationOnScreen(); + Point endPoint = new Point(startPoint); + startPoint.translate(50, 50); + endPoint.translate(150, 150); + + robot.mouseMove(startPoint.x, startPoint.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + for (Point p = new Point(startPoint); !p.equals(endPoint); + p.translate(sign(endPoint.x - p.x), + sign(endPoint.y - p.y))) { + robot.mouseMove(p.x, p.y); + robot.delay(50); + } + + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + if (incorrectActionDetected) { + throw new RuntimeException("User action reported incorrectly."); + } + } + + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } +} diff --git a/test/jdk/java/awt/dnd/RemoveDragSourceListenerTest.java b/test/jdk/java/awt/dnd/RemoveDragSourceListenerTest.java new file mode 100644 index 00000000000..21773e43cde --- /dev/null +++ b/test/jdk/java/awt/dnd/RemoveDragSourceListenerTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2002, 2023, 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 4530216 + @summary tests that DragSourceListeners are properly removed + @key headful + @run main RemoveDragSourceListenerTest +*/ + +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceListener; +import java.awt.dnd.DragSourceMotionListener; + + +public class RemoveDragSourceListenerTest { + public static void main(String[] args) { + class TestDragSourceAdapter extends DragSourceAdapter {} + + final DragSource dragSource = DragSource.getDefaultDragSource(); + + final DragSourceAdapter listeners[] = { + new TestDragSourceAdapter(), + new TestDragSourceAdapter(), + new TestDragSourceAdapter() // should be three or more listeners + }; + + for (int i = 0; i < listeners.length; i++) { + dragSource.addDragSourceListener(listeners[i]); + } + + DragSourceListener[] dragSourceListeners = + dragSource.getDragSourceListeners(); + + if (dragSourceListeners.length != listeners.length) { + throw new RuntimeException("Unexpected length: " + + dragSourceListeners.length); + } + + for (int i = 0; i < listeners.length; i++) { + dragSource.removeDragSourceListener(listeners[i]); + } + + for (int i = 0; i < listeners.length; i++) { + dragSource.addDragSourceMotionListener(listeners[i]); + } + + DragSourceMotionListener[] dragSourceMotionListeners = + dragSource.getDragSourceMotionListeners(); + + if (dragSourceMotionListeners.length != listeners.length) { + throw new RuntimeException("Unexpected length: " + + dragSourceMotionListeners.length); + } + + for (int i = 0; i < listeners.length; i++) { + dragSource.removeDragSourceMotionListener(listeners[i]); + } + } +} diff --git a/test/jdk/java/awt/dnd/RemoveParentChildDropTargetTest.java b/test/jdk/java/awt/dnd/RemoveParentChildDropTargetTest.java new file mode 100644 index 00000000000..2981c8c9337 --- /dev/null +++ b/test/jdk/java/awt/dnd/RemoveParentChildDropTargetTest.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2001, 2023, 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 4411368 + @summary tests the app doesn't crash if the child drop target is removed + after the parent drop target is removed + @key headful + @run main RemoveParentChildDropTargetTest +*/ + +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Panel; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetAdapter; +import java.awt.dnd.DropTargetDropEvent; +import java.lang.reflect.InvocationTargetException; + + +public class RemoveParentChildDropTargetTest { + + static Frame frame; + static Panel panel; + static Label label; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException { + EventQueue.invokeAndWait(() -> { + frame = new Frame("RemoveParentChildDropTargetTest"); + panel = new Panel(); + label = new Label("Label"); + panel.add(label); + frame.add(panel); + frame.pack(); + + panel.setDropTarget(new DropTarget(panel, new DropTargetAdapter() { + public void drop(DropTargetDropEvent dtde) {} + })); + label.setDropTarget(new DropTarget(label, new DropTargetAdapter() { + public void drop(DropTargetDropEvent dtde) {} + })); + panel.setDropTarget(null); + frame.setVisible(true); + + label.setDropTarget(null); + }); + + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } +} diff --git a/test/jdk/java/awt/dnd/SameJVMModalDialogDeadlockTest.java b/test/jdk/java/awt/dnd/SameJVMModalDialogDeadlockTest.java new file mode 100644 index 00000000000..b45ec12ac60 --- /dev/null +++ b/test/jdk/java/awt/dnd/SameJVMModalDialogDeadlockTest.java @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2002, 2023, 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 4484572 4645584 + @summary verifies that showing a modal dialog during the drag operation + in the same JVM doesn't cause hang + @key headful + @run main SameJVMModalDialogDeadlockTest +*/ + +import java.awt.AWTEvent; +import java.awt.AWTException; +import java.awt.Component; +import java.awt.Dialog; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.datatransfer.StringSelection; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceAdapter; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.event.AWTEventListener; +import java.awt.event.InputEvent; +import java.awt.event.MouseEvent; +import java.lang.reflect.InvocationTargetException; + + +public class SameJVMModalDialogDeadlockTest implements AWTEventListener { + + Frame frame; + boolean shown = false; + boolean finished = false; + + final DragSource dragSource = DragSource.getDefaultDragSource(); + final Transferable transferable = new StringSelection("TEXT"); + final DragSourceAdapter dragSourceAdapter = new DragSourceAdapter() { + public void dragDropEnd(DragSourceDropEvent dsde) { + finished = true; + } + public void dragMouseMoved(DragSourceDragEvent dsde) { + if (shown) { + return; + } + + shown = true; + final Dialog d = new Dialog(frame, "Dialog"); + d.setModal(true); + + Runnable r1 = () -> d.setVisible(true); + new Thread(r1).start(); + } + }; + final DragGestureListener dragGestureListener = dge -> + dge.startDrag(null, transferable); + + static final Object SYNC_LOCK = new Object(); + static final int FRAME_ACTIVATION_TIMEOUT = 3000; + static final int DROP_COMPLETION_TIMEOUT = 5000; + static final int MOUSE_RELEASE_TIMEOUT = 1000; + + Component clickedComponent = null; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + SameJVMModalDialogDeadlockTest sameJVMModalDialogDeadlockTest = + new SameJVMModalDialogDeadlockTest(); + EventQueue.invokeAndWait(sameJVMModalDialogDeadlockTest::init); + sameJVMModalDialogDeadlockTest.start(); + } + + public void init() { + frame = new Frame("SameJVMModalDialogDeadlockTest"); + frame.setTitle("Test frame"); + frame.setBounds(100, 100, 200, 200); + dragSource.createDefaultDragGestureRecognizer(frame, + DnDConstants.ACTION_COPY_OR_MOVE, dragGestureListener); + + dragSource.addDragSourceMotionListener(dragSourceAdapter); + dragSource.addDragSourceListener(dragSourceAdapter); + + frame.getToolkit().addAWTEventListener(this, AWTEvent.MOUSE_EVENT_MASK); + frame.setVisible(true); + } + + public void start() throws AWTException, InterruptedException, + InvocationTargetException { + try { + final Robot robot = new Robot(); + robot.waitForIdle(); + robot.delay(FRAME_ACTIVATION_TIMEOUT); + + final Point srcPoint = frame.getLocationOnScreen(); + Dimension d = frame.getSize(); + srcPoint.translate(d.width / 2, d.height / 2); + + if (!pointInComponent(robot, srcPoint, frame)) { + System.err.println("WARNING: Couldn't locate source frame."); + return; + } + + final Point dstPoint = new Point(srcPoint); + dstPoint.translate(d.width / 4, d.height / 4); + + robot.mouseMove(srcPoint.x, srcPoint.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + for (;!srcPoint.equals(dstPoint); + srcPoint.translate(sign(dstPoint.x - srcPoint.x), + sign(dstPoint.y - srcPoint.y))) { + robot.mouseMove(srcPoint.x, srcPoint.y); + robot.delay(50); + } + + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.delay(DROP_COMPLETION_TIMEOUT); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + if (!finished) { + throw new RuntimeException("DnD not completed"); + } + } + + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } + + public void reset() { + clickedComponent = null; + } + + public void eventDispatched(AWTEvent e) { + if (e.getID() == MouseEvent.MOUSE_RELEASED) { + clickedComponent = (Component)e.getSource(); + synchronized (SYNC_LOCK) { + SYNC_LOCK.notifyAll(); + } + } + } + + boolean pointInComponent(Robot robot, Point p, Component comp) + throws InterruptedException { + robot.waitForIdle(); + reset(); + robot.mouseMove(p.x, p.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + synchronized (SYNC_LOCK) { + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + SYNC_LOCK.wait(MOUSE_RELEASE_TIMEOUT); + } + + Component c = clickedComponent; + + while (c != null && c != comp) { + c = c.getParent(); + } + + return c == comp; + } +} diff --git a/test/jdk/java/awt/dnd/SkipDropCompleteTest/SkipDropCompleteTest.java b/test/jdk/java/awt/dnd/SkipDropCompleteTest/SkipDropCompleteTest.java new file mode 100644 index 00000000000..c3474737d5b --- /dev/null +++ b/test/jdk/java/awt/dnd/SkipDropCompleteTest/SkipDropCompleteTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2000, 2023, 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 4187912 + @summary Test that incorrectly written DnD code cannot hang the app + @key headful + @run main SkipDropCompleteTest +*/ + +import java.awt.AWTException; +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.lang.reflect.InvocationTargetException; + + +public class SkipDropCompleteTest { + SourceFrame sourceFrame; + TargetFrame targetFrame; + Point sourceLoc; + Point targetLoc; + + public static void main(String[] args) throws InterruptedException, + InvocationTargetException, AWTException { + SkipDropCompleteTest skipDropCompleteTest = new SkipDropCompleteTest(); + EventQueue.invokeAndWait(skipDropCompleteTest::init); + skipDropCompleteTest.start(); + } + + public void init() { + sourceFrame = new SourceFrame(); + targetFrame = new TargetFrame(); + + sourceLoc = sourceFrame.getLocation(); + Dimension sourceSize = sourceFrame.getSize(); + sourceLoc.x += sourceSize.width / 2; + sourceLoc.y += sourceSize.height / 2; + + targetLoc = targetFrame.getLocation(); + Dimension targetSize = targetFrame.getSize(); + targetLoc.x += targetSize.width / 2; + targetLoc.y += targetSize.height / 2; + } + + public void start() throws AWTException, InterruptedException, + InvocationTargetException { + try { + Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.delay(1000); + robot.mouseMove(sourceLoc.x, sourceLoc.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + for (;!sourceLoc.equals(targetLoc); + sourceLoc.translate(sign(targetLoc.x - sourceLoc.x), + sign(targetLoc.y - sourceLoc.y))) { + robot.mouseMove(sourceLoc.x, sourceLoc.y); + Thread.sleep(10); + } + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + } finally { + EventQueue.invokeAndWait(() -> { + if (sourceFrame != null) { + sourceFrame.dispose(); + } + if (targetFrame != null) { + targetFrame.dispose(); + } + }); + } + + System.out.println("test passed"); + } + + public static int sign(int n) { + return n < 0 ? -1 : n == 0 ? 0 : 1; + } +} diff --git a/test/jdk/java/awt/dnd/SkipDropCompleteTest/SourceFrame.java b/test/jdk/java/awt/dnd/SkipDropCompleteTest/SourceFrame.java new file mode 100644 index 00000000000..2a5af985ba9 --- /dev/null +++ b/test/jdk/java/awt/dnd/SkipDropCompleteTest/SourceFrame.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2000, 2023, 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.awt.Color; +import java.awt.Frame; +import java.awt.TextArea; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DragGestureEvent; +import java.awt.dnd.DragGestureListener; +import java.awt.dnd.DragSource; +import java.awt.dnd.DragSourceDragEvent; +import java.awt.dnd.DragSourceDropEvent; +import java.awt.dnd.DragSourceEvent; +import java.awt.dnd.DragSourceListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +public class SourceFrame extends Frame + implements DragSourceListener,DragGestureListener { + + DragSource dragSource; + TransferableObject transferableObject; + TextArea textArea; + + public SourceFrame() { + + super("SkipDropCompleteTest Source Frame"); + + dragSource = new DragSource(); + textArea = new TextArea("Drag the Text from the SourceFrame\n" + + "and drop it on the TextArea in the\n" + + "Target Frame.\n" + + "Try to do some operation, like closing\n" + + "of the frame.\n"+ + "See whether the application hangs."); + add(textArea); + + dragSource.createDefaultDragGestureRecognizer(textArea, DnDConstants.ACTION_COPY, this); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + setSize(250,250); + setLocation(50,50); + setBackground(Color.red); + this.setVisible(true); + } + + public void dragEnter(DragSourceDragEvent dsde) { } + + public void dragOver(DragSourceDragEvent dsde) { } + + public void dragExit(DragSourceEvent dse) { } + + public void dropActionChanged(DragSourceDragEvent dsde ) { } + + public void dragDropEnd(DragSourceDropEvent dsde) { } + + public void dragGestureRecognized(DragGestureEvent dge) { + transferableObject = new TransferableObject(textArea.getText()); + dragSource.startDrag(dge, DragSource.DefaultCopyDrop, + transferableObject, this); + } +} diff --git a/test/jdk/java/awt/dnd/SkipDropCompleteTest/TargetFrame.java b/test/jdk/java/awt/dnd/SkipDropCompleteTest/TargetFrame.java new file mode 100644 index 00000000000..70b7bf72cb7 --- /dev/null +++ b/test/jdk/java/awt/dnd/SkipDropCompleteTest/TargetFrame.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2000, 2023, 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.awt.Frame; +import java.awt.TextArea; +import java.awt.datatransfer.Transferable; +import java.awt.dnd.DnDConstants; +import java.awt.dnd.DropTarget; +import java.awt.dnd.DropTargetDragEvent; +import java.awt.dnd.DropTargetDropEvent; +import java.awt.dnd.DropTargetEvent; +import java.awt.dnd.DropTargetListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +public class TargetFrame extends Frame implements DropTargetListener{ + + DropTarget dropTarget; + TextArea textArea; + + public TargetFrame() { + super("SkipDropCompleteTest Target Frame"); + textArea = new TextArea(); + add(textArea); + + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + System.exit(0); + } + }); + + setSize(250,250); + setLocation(350,50); + this.setVisible(true); + + dropTarget = new DropTarget(textArea,this); + } + + public void dragEnter(DropTargetDragEvent dtde) { + dtde.acceptDrag(DnDConstants.ACTION_COPY); + } + + public void dragOver(DropTargetDragEvent dtde) {} + + public void dragExit(DropTargetEvent dte) { } + + public void dropActionChanged(DropTargetDragEvent dtde ) {} + + public void drop(DropTargetDropEvent dtde) { + try { + Transferable transferable = dtde.getTransferable(); + dtde.acceptDrop(DnDConstants.ACTION_MOVE); + + String str = (String)transferable.getTransferData(TransferableObject.stringFlavor); + textArea.setText(str); + } catch (Exception ufException ) { + ufException.printStackTrace(); + System.err.println( "Exception" + ufException.getMessage()); + dtde.rejectDrop(); + } + } +} diff --git a/test/jdk/java/awt/dnd/SkipDropCompleteTest/TransferableObject.java b/test/jdk/java/awt/dnd/SkipDropCompleteTest/TransferableObject.java new file mode 100644 index 00000000000..63592ae6fc2 --- /dev/null +++ b/test/jdk/java/awt/dnd/SkipDropCompleteTest/TransferableObject.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2000, 2023, 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.awt.datatransfer.DataFlavor; +import java.awt.datatransfer.Transferable; +import java.awt.datatransfer.UnsupportedFlavorException; +import java.util.Vector; + + +public class TransferableObject implements Transferable { + private Object data; + private String stringText; + public static DataFlavor stringFlavor,localObjectFlavor; + + static + { + // Data Flavor for Java Local Object + try { + localObjectFlavor = new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType); + stringFlavor = DataFlavor.stringFlavor; + } + catch (ClassNotFoundException e) { + System.out.println("Exception " + e); + } + } + + DataFlavor[] dfs; + + public TransferableObject(Object data) { + super(); + Vector v = new Vector(); + if(data instanceof String) { + v.addElement(stringFlavor); + stringText = (String)data; + } + else { + v.addElement(localObjectFlavor); + } + + dfs = new DataFlavor[v.size()]; + v.copyInto(dfs); + + this.data = data; + } + + // Retrieve the data based on the flavor + public Object getTransferData(DataFlavor flavor) + throws UnsupportedFlavorException { + + System.out.println("\n ***************************************"); + System.out.println(" The Flavor passed to retrieve the data : " + + flavor.getHumanPresentableName()); + System.out.println(" The Flavors supported"); + for (int j = 0; j < dfs.length; j++) + System.out.println(" Flavor : " + dfs[j].getHumanPresentableName()); + + System.out.println(" ***************************************\n"); + + if (!isDataFlavorSupported(flavor)) { + throw new UnsupportedFlavorException(flavor); + } else if (flavor.equals(stringFlavor)) { + return stringText; + } else if (localObjectFlavor.isMimeTypeEqual(flavor)) { + return data; + } + return null; + } + + public DataFlavor[] getTransferDataFlavors(){ + return dfs; + } + + public boolean isDataFlavorSupported(DataFlavor flavor) { + for (int i = 0 ; i < dfs.length; i++) { + if (dfs[i].match(flavor)) { + return true; + } + } + return false; + } + +} diff --git a/test/jdk/java/awt/event/KeyEvent/FunctionKeyTest.java b/test/jdk/java/awt/event/KeyEvent/FunctionKeyTest.java new file mode 100644 index 00000000000..fc02cc1d93f --- /dev/null +++ b/test/jdk/java/awt/event/KeyEvent/FunctionKeyTest.java @@ -0,0 +1,140 @@ +/* + * Copyright (c) 1998, 2023, 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.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.Event; +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Label; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.event.KeyEvent; + +/* + * @test + * @bug 4011219 + * @summary Test for function key press/release received by Java client. + * @key headful + */ + +public class FunctionKeyTest { + private static FunctionKeyTester frame; + private static Robot robot; + + static volatile boolean keyPressReceived; + static volatile boolean keyReleaseReceived; + + static final StringBuilder failures = new StringBuilder(); + + private static void testKey(int keyCode, String keyText) { + keyPressReceived = false; + keyReleaseReceived = false; + + robot.keyPress(keyCode); + + if (!keyPressReceived) { + failures.append(keyText).append(" key press is not received\n"); + } + + robot.keyRelease(keyCode); + + if (!keyReleaseReceived) { + failures.append(keyText).append(" key release is not received\n"); + } + } + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.setAutoDelay(150); + + try { + EventQueue.invokeAndWait(() -> { + frame = new FunctionKeyTester(); + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + robot.waitForIdle(); + robot.delay(1000); + + testKey(KeyEvent.VK_F11, "F11"); + testKey(KeyEvent.VK_F12, "F12"); + } finally { + EventQueue.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + + if (failures.length() == 0) { + System.out.println("Passed"); + } else { + throw new RuntimeException(failures.toString()); + } + } +} + +class FunctionKeyTester extends Frame { + Label l = new Label ("NULL"); + Button b = new Button(); + TextArea log = new TextArea(); + + FunctionKeyTester() { + super("Function Key Test"); + this.setLayout(new BorderLayout()); + this.add(BorderLayout.NORTH, l); + this.add(BorderLayout.SOUTH, b); + this.add(BorderLayout.CENTER, log); + log.setFocusable(false); + log.setEditable(false); + l.setBackground(Color.red); + setSize(200, 200); + } + + public boolean handleEvent(Event e) { + String message = "e.id=" + e.id + "\n"; + System.out.print(message); + log.append(message); + + switch (e.id) { + case 403: + FunctionKeyTest.keyPressReceived = true; + break; + case 404: + FunctionKeyTest.keyReleaseReceived = true; + break; + } + + return super.handleEvent(e); + } + + public boolean keyDown(Event e, int key) { + l.setText("e.key=" + Integer.valueOf(e.key).toString()); + return false; + } +} diff --git a/test/jdk/java/awt/event/MouseEvent/ClickDuringKeypress/ClickDuringKeypress.java b/test/jdk/java/awt/event/MouseEvent/ClickDuringKeypress/ClickDuringKeypress.java index 2f0affd5620..ae757bb7d4e 100644 --- a/test/jdk/java/awt/event/MouseEvent/ClickDuringKeypress/ClickDuringKeypress.java +++ b/test/jdk/java/awt/event/MouseEvent/ClickDuringKeypress/ClickDuringKeypress.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2024, 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 @@ -21,116 +21,89 @@ * questions. */ +import java.awt.EventQueue; +import java.awt.Frame; +import java.awt.Robot; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + /* - @test 1.2 98/08/05 + @test @key headful @bug 4515763 @summary Tests that clicking mouse and pressing keys generates correct amount of click-counts - @author andrei.dmitriev: area=awt.mouse @run main ClickDuringKeypress */ -/** - * ClickDuringKeypress.java - * - * summary: - */ - -import java.applet.Applet; -import java.awt.*; -import java.awt.event.*; +public class ClickDuringKeypress implements MouseListener { -public class ClickDuringKeypress implements MouseListener - { - //Declare things used in the test, like buttons and labels here final static int CLICKCOUNT = 10; - final static int DOUBLE_CLICK_AUTO_DELAY = 10; - volatile int lastClickCount = 0; - volatile boolean clicked = false; - volatile boolean ready = false; - - Frame frame; - Robot robot; - - public void init() - { - //Create instructions for the user here, as well as set up - // the environment -- set the layout manager, add buttons, - // etc. - + final static int DOUBLE_CLICK_AUTO_DELAY = 20; + static volatile int lastClickCount = 0; + static volatile boolean clicked = false; + static volatile boolean ready = false; + + static volatile Frame frame; + static volatile Robot robot; + static final ClickDuringKeypress clicker = new ClickDuringKeypress(); + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(ClickDuringKeypress::createUI); + robot = new Robot(); + robot.setAutoWaitForIdle(true); + robot.delay(2000); + robot.mouseMove(200, 200); + robot.delay(2000); + EventQueue.invokeAndWait(() -> frame.setVisible(true)); + doTest(); + } finally { + if (frame != null) { + EventQueue.invokeAndWait(frame::dispose); + } + } + } + + static void createUI() { frame = new Frame("ClickDuringKeypress"); - frame.addMouseListener(this); + frame.addMouseListener(clicker); frame.addWindowListener(new WindowAdapter() { public void windowActivated(WindowEvent e) { - synchronized(ClickDuringKeypress.this) { ready = true; - ClickDuringKeypress.this.notifyAll(); - } } }); frame.setBounds(0, 0, 400, 400); + } - start(); - - }//End init() - - public void start () - { - try { - robot = new Robot(); - } catch (AWTException e) { - System.out.println("Could not create Robot."); - throw new RuntimeException("Couldn't create Robot. Test fails"); - } - - robot.mouseMove(200, 200); - frame.show(); - - synchronized(this) { - try { - if (!ready) { - wait(10000); - } - } catch (InterruptedException ex) { - } - if (!ready) { - System.out.println("Not Activated. Test fails"); - throw new RuntimeException("Not Activated. Test fails"); - } + static void doTest() throws Exception { + robot.waitForIdle(); + robot.delay(1000); + if (!ready) { + System.out.println("Not Activated. Test fails"); + throw new RuntimeException("Not Activated. Test fails"); } - - doTest(); - - //What would normally go into main() will probably go here. - //Use System.out.println for diagnostic messages that you want - //to read after the test is done. - //Use Sysout.println for messages you want the tester to read. - - }// start() - - // Mouse should be over the Frame by this point - private void doTest() { + // Mouse should be over the Frame by this point robot.setAutoDelay(2000); robot.waitForIdle(); robot.keyPress(KeyEvent.VK_B); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.delay(10); - robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); // Should trigger mouseClicked robot.keyRelease(KeyEvent.VK_B); robot.delay(1000); robot.setAutoDelay(DOUBLE_CLICK_AUTO_DELAY); for (int i = 0; i < CLICKCOUNT / 2; i++) { - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.delay(10); - robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); robot.keyPress(KeyEvent.VK_B); - robot.delay(10); robot.keyRelease(KeyEvent.VK_B); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.delay(10); - robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); } robot.waitForIdle(); // check results @@ -156,9 +129,4 @@ public void mouseClicked(MouseEvent e) { clicked = true; lastClickCount = e.getClickCount(); } - - public static void main(String[] args) { - new ClickDuringKeypress().init(); - } - - }// class ClickDuringKeypress +} diff --git a/test/jdk/java/awt/font/Rotate/RotateTest3.java b/test/jdk/java/awt/font/Rotate/RotateTest3.java new file mode 100644 index 00000000000..0241e65e1eb --- /dev/null +++ b/test/jdk/java/awt/font/Rotate/RotateTest3.java @@ -0,0 +1,114 @@ +/* + * Copyright (c) 1999, 2023, 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.awt.Color; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.GridLayout; +import java.awt.Panel; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; + +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +/* + * @test + * @key headful + * @bug 4240228 + * @summary This test is designed to test for a crashing bug in the zh + * locale on Solaris. Rotated text should be displayed, but + * anything other than a crash passes the specific test. + * For example, the missing glyph empty box may be displayed + * in some locales, or no text at all. + */ + +public class RotateTest3 extends Panel { + static JFrame frame; + + protected Java2DView java2DView; + + public RotateTest3(){ + this.setLayout(new GridLayout(1, 1)); + this.setSize(300, 300); + this.java2DView = new Java2DView(); + this.add(this.java2DView); + } + + public static void main(String[] s) throws Exception { + try { + SwingUtilities.invokeAndWait(RotateTest3::initAndShowGui); + Thread.sleep(1000); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + private static void initAndShowGui() { + RotateTest3 panel = new RotateTest3(); + + frame = new JFrame("RotateTest3"); + frame.addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + frame.dispose(); + } + }); + frame.getContentPane().setLayout(new GridLayout(1, 1)); + frame.getContentPane().add("Center", panel); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + static public class Java2DView extends Component { + + public void paint(Graphics g){ + Graphics2D g2d = (Graphics2D) g; + Dimension d = this.getSize(); + g.setColor(this.getBackground()); + g.fillRect(0, 0, d.width, d.height); + g2d.setPaint(Color.black); + + g2d.translate(150,150); + g2d.rotate(-Math.PI / 3); + + String testString = + "\u4e00\u4e8c\u4e09\u56db\u4e94\u516d\u4e03\u516b\u4e5d\u5341"; + g2d.drawString(testString, 0, 0); + } + + public Dimension getMinimumSize(){ + return new Dimension(300, 300); + } + + public Dimension getPreferredSize(){ + return new Dimension(300, 300); + } + } +} diff --git a/test/jdk/java/awt/font/TextLayout/ArabicBox.java b/test/jdk/java/awt/font/TextLayout/ArabicBox.java new file mode 100644 index 00000000000..6b9ccb7cdf0 --- /dev/null +++ b/test/jdk/java/awt/font/TextLayout/ArabicBox.java @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2001, 2024, 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.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.font.FontRenderContext; +import java.awt.font.TextLayout; + +import javax.swing.JPanel; + +/* + * @test + * @bug 4427483 + * @summary Arabic text followed by newline should have no missing glyphs + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual ArabicBox + */ +public final class ArabicBox { + + private static final String TEXT = + "\u0627\u0644\u0639\u0631\u0628\u064A\u0629\n"; + + private static final String FONT_NAME = Font.DIALOG; + + private static final String INSTRUCTIONS = "In the below panel, you should see the following text:\n\n" + + TEXT + "(It's \u2018Arabic\u2019 in Arabic.)\n\n" + + "If there are no 'box glyphs' for missing glyphs,\n" + + "press Pass; otherwise, press Fail."; + + public static void main(String[] args) throws Exception { + final Font font = new Font(FONT_NAME, Font.PLAIN, 24); + System.out.println("asked for " + FONT_NAME + " and got: " + font.getFontName()); + + PassFailJFrame.builder() + .title("Arabic Box") + .instructions(INSTRUCTIONS) + .rows(7) + .columns(40) + .splitUIBottom(() -> createPanel(font)) + .build() + .awaitAndCheck(); + } + + private static JPanel createPanel(Font font) { + return new TextPanel(font); + } + + private static final class TextPanel extends JPanel { + private TextLayout layout; + + private TextPanel(Font font) { + setForeground(Color.black); + setBackground(Color.white); + setFont(font); + setPreferredSize(new Dimension(300, 150)); + } + + @Override + public void paint(Graphics g) { + super.paint(g); + Graphics2D g2d = (Graphics2D)g; + if (layout == null) { + Font font = g2d.getFont(); + FontRenderContext frc = g2d.getFontRenderContext(); + + layout = new TextLayout(TEXT, font, frc); + System.out.println(layout.getBounds()); + } + + layout.draw(g2d, 10, 50); + g2d.drawString(TEXT, 10, 100); + } + } +} diff --git a/test/jdk/java/awt/font/TextLayout/TestJustification.html b/test/jdk/java/awt/font/TextLayout/TestJustification.html deleted file mode 100644 index c9e79f44cb2..00000000000 --- a/test/jdk/java/awt/font/TextLayout/TestJustification.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - -Test Justification - - - -

    Test Justification

    -
    -

    Five lines of text should appear, all justified to the same width, -followed by a sixth line containing only roman characters and no spaces -which is not justified, and instead is centered. -Carets should appear between all characters. Pass the test if this is -true. -

    - -alt="Your browser understands the <APPLET> tag but isn't running the applet, for some reason." -Your browser is completely ignoring the <APPLET> tag! - - - - diff --git a/test/jdk/java/awt/font/TextLayout/TestJustification.java b/test/jdk/java/awt/font/TextLayout/TestJustification.java index 417ddd5adfc..34eca8aed3c 100644 --- a/test/jdk/java/awt/font/TextLayout/TestJustification.java +++ b/test/jdk/java/awt/font/TextLayout/TestJustification.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2024, 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 @@ -21,229 +21,238 @@ * questions. */ +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Font; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.Graphics2D; +import java.awt.Insets; +import java.awt.Panel; +import java.awt.Rectangle; +import java.awt.Shape; +import java.awt.font.FontRenderContext; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.awt.geom.Rectangle2D; +import java.text.AttributedCharacterIterator; +import java.text.AttributedString; + /* - * - * See TestJustification.html for main test. + * @test + * @bug 4211728 4178140 8145542 + * @summary Justify several lines of text and verify that the lines are the same + length and cursor positions are correct. + Bug 4211728: TextLayout.draw() draws characters at wrong position. + Bug 4178140: TextLayout does not justify. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestJustification */ -import java.applet.*; -import java.awt.*; -import java.awt.event.*; -import java.awt.font.*; -import java.awt.geom.*; -import java.text.*; - -public class TestJustification extends Applet { - JustificationPanel panel; - - public void init() { - setLayout(new BorderLayout()); - panel = new JustificationPanel("Bitstream Cyberbit"); - add("Center", panel); - } - - public void destroy() { - remove(panel); - } - - // calls system.exit, not for use in tests. - public static void main(String args[]) { - TestJustification justificationTest = new TestJustification(); - justificationTest.init(); - justificationTest.start(); - - Frame f = new Frame("Test Justification"); - f.addWindowListener(new WindowAdapter() { - public void windowClosing(WindowEvent e) { - System.exit(0); - } - }); - - f.add("Center", justificationTest); - f.setSize(500, 500); - f.show(); - } - - public String getAppletInfo() { - return "Test TextLayout.getJustifiedLayout()"; - } - - static class JustificationPanel extends Panel { - TextLayout[] layouts; - String fontname; - float height; - float oldfsize; - - AttributedCharacterIterator lineText; - TextLayout[] lines; - int linecount; - float oldwidth; - - JustificationPanel(String fontname) { - this.fontname = fontname; +public class TestJustification { + private static final String INSTRUCTIONS = "Five lines of text should appear, all justified to the same width,\n" + + "followed by a sixth line containing only roman characters and\n" + + "no spaces which is not justified, and instead is centered.\n" + + "Carets should appear between all characters.\n\n" + + "PASS the test if this is true, else press FAIL."; + + public static void main(String[] args) throws Exception { + + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(35) + .testUI(TestJustification::createUI) + .build() + .awaitAndCheck(); } - private static final String[] texts = { - "This is an english Highlighting demo.", "Highlighting", - "This is an arabic \u0627\u0628\u062a\u062c \u062e\u0644\u0627\u062e demo.", "arabic \u0627\u0628\u062a\u062c", - "This is a hebrew \u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5 demo.", "hebrew \u05d0\u05d1\u05d2", - "This is a cjk \u4e00\u4e01\u4e02\uac00\uac01\uc4fa\uf900\uf901\uf902 demo.", "cjk", - "NoSpaceCJK:\u4e00\u4e01\u4e02and\uac00\uac01\uc4faand\uf900\uf901\uf902", "No", - "NoSpaceRoman", "Space" - }; + private static Frame createUI() { + Frame frame= new Frame("Test Text Justification"); + JustificationPanel panel = new JustificationPanel("Bitstream Cyberbit"); + frame.add(panel); + frame.add("Center", panel); + frame.setSize(500, 450); + return frame; + } - public void paint(Graphics g) { - Graphics2D g2d = (Graphics2D)g; + static class JustificationPanel extends Panel { + TextLayout[] layouts; + String fontname; + float height; + float oldfsize; - Dimension d = getSize(); - Insets insets = getInsets(); + AttributedCharacterIterator lineText; + TextLayout[] lines; + int linecount; + float oldwidth; - float w = d.width - insets.left - insets.right; - float h = d.height - insets.top - insets.bottom; - int fsize = (int)w/25; + JustificationPanel(String fontname) { + this.fontname = fontname; + } - FontRenderContext frc = g2d.getFontRenderContext(); + private static final String[] texts = { + "This is an english Highlighting demo.", "Highlighting", + "This is an arabic \u0627\u0628\u062a\u062c \u062e\u0644\u0627\u062e demo.", "arabic \u0627\u0628\u062a\u062c", + "This is a hebrew \u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5 demo.", "hebrew \u05d0\u05d1\u05d2", + "This is a cjk \u4e00\u4e01\u4e02\uac00\uac01\uc4fa\uf900\uf901\uf902 demo.", "cjk", + "NoSpaceCJK:\u4e00\u4e01\u4e02and\uac00\uac01\uc4faand\uf900\uf901\uf902", "No", + "NoSpaceRoman", "Space" + }; - if (layouts == null || fsize != oldfsize) { - oldfsize = fsize; + public void paint(Graphics g) { + Graphics2D g2d = (Graphics2D)g; - Font f0 = new Font(fontname, Font.PLAIN, fsize); - Font f1 = new Font(fontname, Font.ITALIC, (int)(fsize * 1.5)); + Dimension d = getSize(); + Insets insets = getInsets(); - if (layouts == null) { - layouts = new TextLayout[texts.length / 2]; - } + float w = d.width - insets.left - insets.right; + float h = d.height - insets.top - insets.bottom; + int fsize = (int)w/25; - height = 0; - for (int i = 0; i < layouts.length; ++i) { - String text = texts[i*2]; - String target = texts[i*2+1]; + FontRenderContext frc = g2d.getFontRenderContext(); - AttributedString astr = new AttributedString(text); - astr.addAttribute(TextAttribute.FONT, f0, 0, text.length()); + if (layouts == null || fsize != oldfsize) { + oldfsize = fsize; - int start = text.indexOf(target); - int limit = start + target.length(); - astr.addAttribute(TextAttribute.FONT, f1, start, limit); + Font f0 = new Font(fontname, Font.PLAIN, fsize); + Font f1 = new Font(fontname, Font.ITALIC, (int)(fsize * 1.5)); - TextLayout layout = new TextLayout(astr.getIterator(), frc); + if (layouts == null) { + layouts = new TextLayout[texts.length / 2]; + } - layout = layout.getJustifiedLayout(w - 20); + height = 0; + for (int i = 0; i < layouts.length; ++i) { + String text = texts[i*2]; + String target = texts[i*2+1]; - layouts[i] = layout; + AttributedString astr = new AttributedString(text); + astr.addAttribute(TextAttribute.FONT, f0, 0, text.length()); + + int start = text.indexOf(target); + int limit = start + target.length(); + astr.addAttribute(TextAttribute.FONT, f1, start, limit); + + TextLayout layout = new TextLayout(astr.getIterator(), frc); - height += layout.getAscent() + layout.getDescent() + layout.getLeading(); - } - } + layout = layout.getJustifiedLayout(w - 20); + + layouts[i] = layout; - g2d.setColor(Color.white); - g2d.fill(new Rectangle.Float(insets.left, insets.top, w, h)); + height += layout.getAscent() + layout.getDescent() + layout.getLeading(); + } + } - float basey = 20; + g2d.setColor(Color.white); + g2d.fill(new Rectangle.Float(insets.left, insets.top, w, h)); - for (int i = 0; i < layouts.length; ++i) { - TextLayout layout = layouts[i]; + float basey = 20; - float la = layout.getAscent(); - float ld = layout.getDescent(); - float ll = layout.getLeading(); - float lw = layout.getAdvance(); - float lh = la + ld + ll; - float lx = (w - lw) / 2f; - float ly = basey + layout.getAscent(); + for (TextLayout layout : layouts) { + float la = layout.getAscent(); + float ld = layout.getDescent(); + float ll = layout.getLeading(); + float lw = layout.getAdvance(); + float lh = la + ld + ll; + float lx = (w - lw) / 2f; + float ly = basey + layout.getAscent(); - g2d.setColor(Color.black); - g2d.translate(insets.left + lx, insets.top + ly); + g2d.setColor(Color.black); + g2d.translate(insets.left + lx, insets.top + ly); - Rectangle2D bounds = new Rectangle2D.Float(0, -la, lw, lh); - g2d.draw(bounds); + Rectangle2D bounds = new Rectangle2D.Float(0, -la, lw, lh); + g2d.draw(bounds); - layout.draw(g2d, 0, 0); + layout.draw(g2d, 0, 0); - g2d.setColor(Color.red); - for (int j = 0, e = layout.getCharacterCount(); j <= e; ++j) { - Shape[] carets = layout.getCaretShapes(j, bounds); - g2d.draw(carets[0]); - } + g2d.setColor(Color.red); + for (int j = 0, e = layout.getCharacterCount(); j <= e; ++j) { + Shape[] carets = layout.getCaretShapes(j, bounds); + g2d.draw(carets[0]); + } - g2d.translate(-insets.left - lx, -insets.top - ly); - basey += layout.getAscent() + layout.getDescent() + layout.getLeading(); - } - - // add LineBreakMeasurer-generated layouts - - if (lineText == null) { - String text = "This is a long line of text that should be broken across multiple " - + "lines and then justified to fit the break width. This test should pass if " - + "these lines are justified to the same width, and fail otherwise. It should " - + "also format the hebrew (\u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5) and arabic " - + "(\u0627\u0628\u062a\u062c \u062e\u0644\u0627\u062e) and CJK " - + "(\u4e00\u4e01\u4e02\uac00\uac01\uc4fa\u67b1\u67b2\u67b3\u67b4\u67b5\u67b6\u67b7" - + "\u67b8\u67b9) text correctly."; - - Float regular = new Float(16.0); - Float big = new Float(24.0); - AttributedString astr = new AttributedString(text); - astr.addAttribute(TextAttribute.SIZE, regular, 0, text.length()); - astr.addAttribute(TextAttribute.FAMILY, fontname, 0, text.length()); - - int ix = text.indexOf("broken"); - astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); - ix = text.indexOf("hebrew"); - astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); - ix = text.indexOf("arabic"); - astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); - ix = text.indexOf("CJK"); - astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 3); - - lineText = astr.getIterator(); - } - - float width = w - 20; - if (lines == null || width != oldwidth) { - oldwidth = width; - - lines = new TextLayout[10]; - linecount = 0; - - LineBreakMeasurer measurer = new LineBreakMeasurer(lineText, frc); - - for (;;) { - TextLayout layout = measurer.nextLayout(width); - if (layout == null) { - break; - } - - // justify all but last line - if (linecount > 0) { - lines[linecount - 1] = lines[linecount - 1].getJustifiedLayout(width); - } - - if (linecount == lines.length) { - TextLayout[] nlines = new TextLayout[lines.length * 2]; - System.arraycopy(lines, 0, nlines, 0, lines.length); - lines = nlines; - } - - lines[linecount++] = layout; - } - } + g2d.translate(-insets.left - lx, -insets.top - ly); + basey += layout.getAscent() + layout.getDescent() + layout.getLeading(); + } - float basex = insets.left + 10; - basey += 10; - g2d.setColor(Color.black); + // add LineBreakMeasurer-generated layouts - for (int i = 0; i < linecount; ++i) { - TextLayout layout = lines[i]; + if (lineText == null) { + String text = "This is a long line of text that should be broken across multiple " + + "lines and then justified to fit the break width. This test should pass if " + + "these lines are justified to the same width, and fail otherwise. It should " + + "also format the hebrew (\u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5) and arabic " + + "(\u0627\u0628\u062a\u062c \u062e\u0644\u0627\u062e) and CJK " + + "(\u4e00\u4e01\u4e02\uac00\uac01\uc4fa\u67b1\u67b2\u67b3\u67b4\u67b5\u67b6\u67b7" + + "\u67b8\u67b9) text correctly."; - basey += layout.getAscent(); - float adv = layout.getAdvance(); - float dx = layout.isLeftToRight() ? 0 : width - adv; + Float regular = 16.0F; + Float big = 24.0F; + AttributedString astr = new AttributedString(text); + astr.addAttribute(TextAttribute.SIZE, regular, 0, text.length()); + astr.addAttribute(TextAttribute.FAMILY, fontname, 0, text.length()); - layout.draw(g2d, basex + dx, basey); + int ix = text.indexOf("broken"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("hebrew"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("arabic"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("CJK"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 3); - basey += layout.getDescent() + layout.getLeading(); - } + lineText = astr.getIterator(); + } + + float width = w - 20; + if (lines == null || width != oldwidth) { + oldwidth = width; + + lines = new TextLayout[10]; + linecount = 0; + + LineBreakMeasurer measurer = new LineBreakMeasurer(lineText, frc); + + for (;;) { + TextLayout layout = measurer.nextLayout(width); + if (layout == null) { + break; + } + + // justify all but last line + if (linecount > 0) { + lines[linecount - 1] = lines[linecount - 1].getJustifiedLayout(width); + } + + if (linecount == lines.length) { + TextLayout[] nlines = new TextLayout[lines.length * 2]; + System.arraycopy(lines, 0, nlines, 0, lines.length); + lines = nlines; + } + + lines[linecount++] = layout; + } + } + + float basex = insets.left + 10; + basey += 10; + g2d.setColor(Color.black); + + for (int i = 0; i < linecount; ++i) { + TextLayout layout = lines[i]; + + basey += layout.getAscent(); + float adv = layout.getAdvance(); + float dx = layout.isLeftToRight() ? 0 : width - adv; + + layout.draw(g2d, basex + dx, basey); + + basey += layout.getDescent() + layout.getLeading(); + } + } } - } } diff --git a/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java b/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java index 15a914934e7..6290d14b428 100644 --- a/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java +++ b/test/jdk/java/awt/regtesthelpers/PassFailJFrame.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, 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 @@ -63,6 +63,7 @@ import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JScrollPane; +import javax.swing.JSplitPane; import javax.swing.JTextArea; import javax.swing.Timer; import javax.swing.text.JTextComponent; @@ -114,6 +115,13 @@ * or a list of windows if the test needs multiple windows, * or directly a single window, an array of windows or a list of windows. *

    + * For simple test UI, use {@code Builder.splitUI}, or explicitly + * {@code Builder.splitUIRight} or {@code Builder.splitUIBottom} with + * a {@code PanelCreator}. The framework will call the provided + * {@code createUIPanel} to create the component with test UI and + * will place it as the right or bottom component in a split pane + * along with instruction UI. + *

    * Alternatively, use one of the {@code PassFailJFrame} constructors to * create an object, then create secondary test UI, register it * with {@code PassFailJFrame}, position it and make it visible. @@ -166,6 +174,14 @@ public final class PassFailJFrame { */ private static final String EMPTY_REASON = "(no reason provided)"; + /** + * List of windows or frames managed by the {@code PassFailJFrame} + * framework. These windows are automatically disposed of when the + * test is finished. + *

    + * Note: access to this field has to be synchronized by + * {@code PassFailJFrame.class}. + */ private static final List windowList = new ArrayList<>(); private static final CountDownLatch latch = new CountDownLatch(1); @@ -276,10 +292,33 @@ public PassFailJFrame(String title, String instructions, long testTimeOut, enableScreenCapture)); } - private PassFailJFrame(Builder builder) throws InterruptedException, - InvocationTargetException { - this(builder.title, builder.instructions, builder.testTimeOut, - builder.rows, builder.columns, builder.screenCapture); + /** + * Configures {@code PassFailJFrame} using the builder. + * It creates test UI specified using {@code testUI} or {@code splitUI} + * methods on EDT. + * @param builder the builder with the parameters + * @throws InterruptedException if the current thread is interrupted while + * waiting for EDT to complete a task + * @throws InvocationTargetException if an exception is thrown while + * running a task on EDT + */ + private PassFailJFrame(final Builder builder) + throws InterruptedException, InvocationTargetException { + invokeOnEDT(() -> createUI(builder)); + + if (!builder.splitUI && builder.panelCreator != null) { + JComponent content = builder.panelCreator.createUIPanel(); + String title = content.getName(); + if (title == null) { + title = "Test UI"; + } + JDialog dialog = new JDialog(frame, title, false); + dialog.addWindowListener(windowClosingHandler); + dialog.add(content, BorderLayout.CENTER); + dialog.pack(); + addTestWindow(dialog); + positionTestWindow(dialog, builder.position); + } if (builder.windowListCreator != null) { invokeOnEDT(() -> @@ -299,11 +338,10 @@ private PassFailJFrame(Builder builder) throws InterruptedException, if (builder.positionWindows != null) { positionInstructionFrame(builder.position); - invokeOnEDT(() -> { - builder.positionWindows - .positionTestWindows(unmodifiableList(builder.testWindows), - builder.instructionUIHandler); - }); + invokeOnEDT(() -> + builder.positionWindows + .positionTestWindows(unmodifiableList(builder.testWindows), + builder.instructionUIHandler)); } else if (builder.testWindows.size() == 1) { Window window = builder.testWindows.get(0); positionTestWindow(window, builder.position); @@ -341,16 +379,61 @@ private static void createUI(String title, String instructions, frame = new JFrame(title); frame.setLayout(new BorderLayout()); + frame.addWindowListener(windowClosingHandler); + + frame.add(createInstructionUIPanel(instructions, + testTimeOut, + rows, columns, + enableScreenCapture), + BorderLayout.CENTER); + frame.pack(); + frame.setLocationRelativeTo(null); + addTestWindow(frame); + } + + private static void createUI(Builder builder) { + frame = new JFrame(builder.title); + frame.setLayout(new BorderLayout()); + + frame.addWindowListener(windowClosingHandler); + + JComponent instructionUI = + createInstructionUIPanel(builder.instructions, + builder.testTimeOut, + builder.rows, builder.columns, + builder.screenCapture); + + if (builder.splitUI) { + JSplitPane splitPane = new JSplitPane( + builder.splitUIOrientation, + instructionUI, + builder.panelCreator.createUIPanel()); + frame.add(splitPane, BorderLayout.CENTER); + } else { + frame.add(instructionUI, BorderLayout.CENTER); + } + + frame.pack(); + frame.setLocationRelativeTo(null); + addTestWindow(frame); + } + + private static JComponent createInstructionUIPanel(String instructions, + long testTimeOut, + int rows, int columns, + boolean enableScreenCapture) { + JPanel main = new JPanel(new BorderLayout()); + JLabel testTimeoutLabel = new JLabel("", JLabel.CENTER); timeoutHandler = new TimeoutHandler(testTimeoutLabel, testTimeOut); - frame.add(testTimeoutLabel, BorderLayout.NORTH); + main.add(testTimeoutLabel, BorderLayout.NORTH); JTextComponent text = instructions.startsWith("") ? configureHTML(instructions, rows, columns) : configurePlainText(instructions, rows, columns); text.setEditable(false); - frame.add(new JScrollPane(text), BorderLayout.CENTER); + main.add(new JScrollPane(text), BorderLayout.CENTER); JButton btnPass = new JButton("Pass"); btnPass.addActionListener((e) -> { @@ -372,12 +455,10 @@ private static void createUI(String title, String instructions, buttonsPanel.add(createCapturePanel()); } - frame.addWindowListener(windowClosingHandler); + main.add(buttonsPanel, BorderLayout.SOUTH); + main.setMinimumSize(main.getPreferredSize()); - frame.add(buttonsPanel, BorderLayout.SOUTH); - frame.pack(); - frame.setLocationRelativeTo(null); - addTestWindow(frame); + return main; } private static JTextComponent configurePlainText(String instructions, @@ -433,6 +514,22 @@ public interface WindowListCreator { List createTestUI(); } + /** + * Creates a component (panel) with test UI + * to be hosted in a split pane or a frame. + */ + @FunctionalInterface + public interface PanelCreator { + /** + * Creates a component which hosts test UI. This component + * is placed into a split pane or into a frame to display the UI. + *

    + * This method is called by the framework on the EDT. + * @return a component (panel) with test UI + */ + JComponent createUIPanel(); + } + /** * Positions test UI windows. */ @@ -634,10 +731,12 @@ private static void captureScreen(CaptureType type) { break; case WINDOWS: - windowList.stream() - .filter(Window::isShowing) - .map(Window::getBounds) - .forEach(PassFailJFrame::captureScreen); + synchronized (PassFailJFrame.class) { + windowList.stream() + .filter(Window::isShowing) + .map(Window::getBounds) + .forEach(PassFailJFrame::captureScreen); + } break; default: @@ -950,6 +1049,9 @@ public static final class Builder { private List testWindows; private WindowListCreator windowListCreator; + private PanelCreator panelCreator; + private boolean splitUI; + private int splitUIOrientation; private PositionWindows positionWindows; private InstructionUI instructionUIHandler; @@ -1090,8 +1192,102 @@ private void checkWindowsLists() { } } - public Builder positionTestUI(PositionWindows positionWindows) { - this.positionWindows = positionWindows; + /** + * Adds a {@code PanelCreator} which the framework will use + * to create a component and place it into a dialog. + * + * @param panelCreator a {@code PanelCreator} to create a component + * with test UI + * @return this builder + * @throws IllegalStateException if split UI was enabled using + * a {@code splitUI} method + */ + public Builder testUI(PanelCreator panelCreator) { + if (splitUI) { + throw new IllegalStateException("Can't combine splitUI and " + + "testUI with panelCreator"); + } + this.panelCreator = panelCreator; + return this; + } + + /** + * Adds a {@code PanelCreator} which the framework will use + * to create a component with test UI and display it in a split pane. + *

    + * By default, horizontal orientation is used, + * and test UI is displayed to the right of the instruction UI. + * + * @param panelCreator a {@code PanelCreator} to create a component + * with test UI + * @return this builder + * + * @throws IllegalStateException if a {@code PanelCreator} is + * already set + * @throws IllegalArgumentException if {panelCreator} is {@code null} + */ + public Builder splitUI(PanelCreator panelCreator) { + return splitUIRight(panelCreator); + } + + /** + * Adds a {@code PanelCreator} which the framework will use + * to create a component with test UI and display it + * to the right of instruction UI. + * + * @param panelCreator a {@code PanelCreator} to create a component + * with test UI + * @return this builder + * + * @throws IllegalStateException if a {@code PanelCreator} is + * already set + * @throws IllegalArgumentException if {panelCreator} is {@code null} + */ + public Builder splitUIRight(PanelCreator panelCreator) { + return splitUI(panelCreator, JSplitPane.HORIZONTAL_SPLIT); + } + + /** + * Adds a {@code PanelCreator} which the framework will use + * to create a component with test UI and display it + * in the bottom of instruction UI. + * + * @param panelCreator a {@code PanelCreator} to create a component + * with test UI + * @return this builder + * + * @throws IllegalStateException if a {@code PanelCreator} is + * already set + * @throws IllegalArgumentException if {panelCreator} is {@code null} + */ + public Builder splitUIBottom(PanelCreator panelCreator) { + return splitUI(panelCreator, JSplitPane.VERTICAL_SPLIT); + } + + /** + * Enables split UI and stores the orientation of the split pane. + * + * @param panelCreator a {@code PanelCreator} to create a component + * with test UI + * @param splitUIOrientation orientation of the split pane + * @return this builder + * + * @throws IllegalStateException if a {@code PanelCreator} is + * already set + * @throws IllegalArgumentException if {panelCreator} is {@code null} + */ + private Builder splitUI(PanelCreator panelCreator, + int splitUIOrientation) { + if (panelCreator == null) { + throw new IllegalArgumentException("A PanelCreator cannot be null"); + } + if (this.panelCreator != null) { + throw new IllegalStateException("A PanelCreator is already set"); + } + + splitUI = true; + this.splitUIOrientation = splitUIOrientation; + this.panelCreator = panelCreator; return this; } @@ -1129,7 +1325,8 @@ private void validate() { } if (position == null - && (testWindows != null || windowListCreator != null)) { + && (testWindows != null || windowListCreator != null + || (!splitUI && panelCreator != null))) { position = Position.HORIZONTAL; } @@ -1137,7 +1334,7 @@ private void validate() { if (positionWindows != null) { if (testWindows == null && windowListCreator == null) { throw new IllegalStateException("To position windows, " - + "provide an a list of windows to the builder"); + + "provide a list of windows to the builder"); } instructionUIHandler = new InstructionUIHandler(); } @@ -1176,6 +1373,11 @@ public Position getPosition() { } } + /** + * Creates a builder for configuring {@code PassFailJFrame}. + * + * @return the builder for configuring {@code PassFailJFrame} + */ public static Builder builder() { return new Builder(); } diff --git a/test/jdk/java/awt/regtesthelpers/Util.java b/test/jdk/java/awt/regtesthelpers/Util.java index 90739ded406..d0ec8bcc5c9 100644 --- a/test/jdk/java/awt/regtesthelpers/Util.java +++ b/test/jdk/java/awt/regtesthelpers/Util.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2022, 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 @@ -410,8 +410,7 @@ public void windowClosing(WindowEvent e) { } /* - * The values directly map to the ones of - * sun.awt.X11.XWM & sun.awt.motif.MToolkit classes. + * The values directly map to the ones of sun.awt.X11.XWM class. */ public final static int UNDETERMINED_WM = 1, @@ -438,8 +437,6 @@ public static int getWMID() { try { if ("sun.awt.X11.XToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { clazz = Class.forName("sun.awt.X11.XWM"); - } else if ("sun.awt.motif.MToolkit".equals(Toolkit.getDefaultToolkit().getClass().getName())) { - clazz = Class.forName("sun.awt.motif.MToolkit"); } } catch (ClassNotFoundException cnfe) { cnfe.printStackTrace(); @@ -451,7 +448,6 @@ public static int getWMID() { try { final Class _clazz = clazz; Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.Module.class); - // No MToolkit anymore: nothing to do about it. // We may be called from non-X11 system, and this permission cannot be delegated to a test. m_addExports.invoke(null, "sun.awt.X11", Util.class.getModule()); Method m_getWMID = (Method)AccessController.doPrivileged(new PrivilegedAction() { diff --git a/test/jdk/java/io/BufferedInputStream/LargeCopyWithMark.java b/test/jdk/java/io/BufferedInputStream/LargeCopyWithMark.java index 0519e1483f0..e3c171c0220 100644 --- a/test/jdk/java/io/BufferedInputStream/LargeCopyWithMark.java +++ b/test/jdk/java/io/BufferedInputStream/LargeCopyWithMark.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,65 +23,42 @@ /* @test * @bug 7129312 + * @requires (sun.arch.data.model == "64" & os.maxMemory > 4g) * @summary BufferedInputStream calculates negative array size with large * streams and mark - * @library /test/lib - * @run main/othervm LargeCopyWithMark + * @run main/othervm -Xmx4G LargeCopyWithMark */ import java.io.BufferedInputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import static jdk.test.lib.process.ProcessTools.*; - public class LargeCopyWithMark { - public static void main(String[] args) throws Exception { - if (! System.getProperty("os.arch").contains("64")) { - System.out.println("Test runs on 64 bit platforms"); - return; - } - ProcessBuilder pb = createJavaProcessBuilder("-Xmx4G", - "-ea:LargeCopyWithMark$Child", - "LargeCopyWithMark$Child"); - int res = pb.inheritIO().start().waitFor(); - if (res != 0) { - throw new AssertionError("Test failed: exit code = " + res); - } - } + static final int BUFF_SIZE = 8192; + static final int BIS_BUFF_SIZE = Integer.MAX_VALUE / 2 + 100; + static final long BYTES_TO_COPY = 2L * Integer.MAX_VALUE; - public static class Child { - static final int BUFF_SIZE = 8192; - static final int BIS_BUFF_SIZE = Integer.MAX_VALUE / 2 + 100; - static final long BYTES_TO_COPY = 2L * Integer.MAX_VALUE; - - static { - assert BIS_BUFF_SIZE * 2 < 0 : "doubling must overflow"; - } + static { + assert BIS_BUFF_SIZE * 2 < 0 : "doubling must overflow"; + } - public static void main(String[] args) throws Exception { - byte[] buff = new byte[BUFF_SIZE]; + public static void main(String[] args) throws Exception { + byte[] buff = new byte[BUFF_SIZE]; - try (InputStream myis = new MyInputStream(BYTES_TO_COPY); - InputStream bis = new BufferedInputStream(myis, BIS_BUFF_SIZE); - OutputStream myos = new MyOutputStream()) { + try (InputStream myis = new MyInputStream(BYTES_TO_COPY); + InputStream bis = new BufferedInputStream(myis, BIS_BUFF_SIZE); + OutputStream myos = new MyOutputStream()) { - // will require a buffer bigger than BIS_BUFF_SIZE - bis.mark(BIS_BUFF_SIZE + 100); + // will require a buffer bigger than BIS_BUFF_SIZE + bis.mark(BIS_BUFF_SIZE + 100); - for (;;) { - int count = bis.read(buff, 0, BUFF_SIZE); - if (count == -1) - break; - myos.write(buff, 0, count); - } - } catch (java.lang.NegativeArraySizeException e) { - e.printStackTrace(); - System.exit(11); - } catch (Exception e) { - e.printStackTrace(); + for (;;) { + int count = bis.read(buff, 0, BUFF_SIZE); + if (count == -1) + break; + myos.write(buff, 0, count); } } } diff --git a/test/jdk/java/io/ObjectInputStream/ResolveProxyClass.java b/test/jdk/java/io/ObjectInputStream/ResolveProxyClass.java index af4980a994d..df993d3e066 100644 --- a/test/jdk/java/io/ObjectInputStream/ResolveProxyClass.java +++ b/test/jdk/java/io/ObjectInputStream/ResolveProxyClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021 Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -38,7 +38,6 @@ * @run main/othervm -Dcom.alibaba.enableFastSerialization=true ResolveProxyClass */ -import java.lang.reflect.*; import java.io.*; public class ResolveProxyClass { @@ -54,7 +53,7 @@ private static class TestObjectInputStream extends ObjectInputStream { super(); } - protected Class resolveProxyClass(String[] interfaces) + protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { return super.resolveProxyClass(interfaces); @@ -84,7 +83,7 @@ public static void main(String[] args) { ClassLoader expectedLoader = ResolveProxyClass.class.getClassLoader(); TestObjectInputStream in = new TestObjectInputStream(); - Class proxyClass = in.resolveProxyClass( + Class proxyClass = in.resolveProxyClass( new String[] { Runnable.class.getName() }); ClassLoader proxyLoader = proxyClass.getClassLoader(); System.err.println("proxy class \"" + proxyClass + diff --git a/test/jdk/java/io/ObjectInputStream/TestObjectStreamClass.java b/test/jdk/java/io/ObjectInputStream/TestObjectStreamClass.java index 1efa1d75b4e..2e7f3f655a9 100644 --- a/test/jdk/java/io/ObjectInputStream/TestObjectStreamClass.java +++ b/test/jdk/java/io/ObjectInputStream/TestObjectStreamClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2021 Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -61,6 +61,8 @@ public static void main(String[] args) throws Exception { } static class TestClass implements Serializable { + private static final long serialVersionUID = 1L; + String str = "hello world"; } diff --git a/test/jdk/java/io/Serializable/ClassCastExceptionDetail/Read.java b/test/jdk/java/io/Serializable/ClassCastExceptionDetail/Read.java index 545d8062ec5..dece8757bd1 100644 --- a/test/jdk/java/io/Serializable/ClassCastExceptionDetail/Read.java +++ b/test/jdk/java/io/Serializable/ClassCastExceptionDetail/Read.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,9 @@ class Foo implements Serializable { private Float bar; } -class Gub extends Foo {} +class Gub extends Foo { + private static final long serialVersionUID = 1L; +} public class Read { public static void main(String[] args) throws Exception { diff --git a/test/jdk/java/io/Serializable/ClassCastExceptionDetail/Write.java b/test/jdk/java/io/Serializable/ClassCastExceptionDetail/Write.java index 9efee3fde6e..1ef7db17bd2 100644 --- a/test/jdk/java/io/Serializable/ClassCastExceptionDetail/Write.java +++ b/test/jdk/java/io/Serializable/ClassCastExceptionDetail/Write.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,10 +41,12 @@ class Foo implements Serializable { private static final long serialVersionUID = 0L; - private Integer bar = new Integer(0); + private Integer bar = 0; } -class Gub extends Foo {} +class Gub extends Foo { + private static final long serialVersionUID = 1L; +} public class Write { public static void main(String[] args) throws Exception { diff --git a/test/jdk/java/io/Serializable/GetField/Read2.java b/test/jdk/java/io/Serializable/GetField/Read2.java index 0a8916e6e2c..e6b4aba0ab4 100644 --- a/test/jdk/java/io/Serializable/GetField/Read2.java +++ b/test/jdk/java/io/Serializable/GetField/Read2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,7 @@ class Foo implements Serializable { float f; double d; String str; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ Object extra; private void readObject(ObjectInputStream in) diff --git a/test/jdk/java/io/Serializable/InvalidClassException/noargctor/DefaultPackage.java b/test/jdk/java/io/Serializable/InvalidClassException/noargctor/DefaultPackage.java index 45fc0966d51..14c41dbc550 100644 --- a/test/jdk/java/io/Serializable/InvalidClassException/noargctor/DefaultPackage.java +++ b/test/jdk/java/io/Serializable/InvalidClassException/noargctor/DefaultPackage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -56,24 +56,33 @@ protected DefaultPackagePrivateConstructor(int i) { class DefaultPublicSerializable extends DefaultPackagePublicConstructor implements Serializable { + private static final long serialVersionUID = 1L; + int field1 = 5; }; class DefaultProtectedSerializable extends DefaultPackageProtectedConstructor implements Serializable { + private static final long serialVersionUID = 1L; + int field1 = 5; }; class DefaultAccessSerializable extends DefaultPackageDefaultAccessConstructor implements Serializable { + private static final long serialVersionUID = 1L; + int field1 = 5; }; +@SuppressWarnings("serial") /* Incorrect declarations are being tested */ class DefaultPrivateSerializable extends DefaultPackagePrivateConstructor implements Serializable { + private static final long serialVersionUID = 1L; + int field1 = 5; DefaultPrivateSerializable() { @@ -82,6 +91,8 @@ class DefaultPrivateSerializable }; class ExternalizablePublicConstructor implements Externalizable { + private static final long serialVersionUID = 1L; + public ExternalizablePublicConstructor() { } public void writeExternal(ObjectOutput out) throws IOException { @@ -92,7 +103,10 @@ public void readExternal(ObjectInput in) } }; +@SuppressWarnings("serial") /* Incorrect declarations are being tested */ class ExternalizableProtectedConstructor implements Externalizable { + private static final long serialVersionUID = 1L; + protected ExternalizableProtectedConstructor() { } public void writeExternal(ObjectOutput out) throws IOException { @@ -103,7 +117,10 @@ public void readExternal(ObjectInput in) } }; +@SuppressWarnings("serial") /* Incorrect declarations are being tested */ class ExternalizableAccessConstructor implements Externalizable { + private static final long serialVersionUID = 1L; + ExternalizableAccessConstructor() { } public void writeExternal(ObjectOutput out) throws IOException { @@ -114,7 +131,10 @@ public void readExternal(ObjectInput in) } }; +@SuppressWarnings("serial") /* Incorrect declarations are being tested */ class ExternalizablePrivateConstructor implements Externalizable { + private static final long serialVersionUID = 1L; + private ExternalizablePrivateConstructor() { } public ExternalizablePrivateConstructor(int i) { diff --git a/test/jdk/java/io/Serializable/InvalidClassException/noargctor/Serialize/SubclassAcrossPackage.java b/test/jdk/java/io/Serializable/InvalidClassException/noargctor/Serialize/SubclassAcrossPackage.java index e869d9df40d..bb7f5444354 100644 --- a/test/jdk/java/io/Serializable/InvalidClassException/noargctor/Serialize/SubclassAcrossPackage.java +++ b/test/jdk/java/io/Serializable/InvalidClassException/noargctor/Serialize/SubclassAcrossPackage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,18 +34,24 @@ class PublicSerializable extends NonSerializable.PublicCtor implements Serializable { + private static final long serialVersionUID = 1L; + int field1 = 5; }; class ProtectedSerializable extends NonSerializable.ProtectedCtor implements Serializable { + private static final long serialVersionUID = 1L; + int field1 = 5; }; class DifferentPackageSerializable extends NonSerializable.PackageCtor implements Serializable { + private static final long serialVersionUID = 1L; + int field1 = 5; DifferentPackageSerializable() { super(1); @@ -55,11 +61,15 @@ class DifferentPackageSerializable class SamePackageSerializable extends Serialize.SamePackageCtor implements Serializable { + private static final long serialVersionUID = 1L; + SamePackageSerializable() { } }; class SamePackageProtectedCtor { + private static final long serialVersionUID = 1L; + protected SamePackageProtectedCtor() { } }; @@ -67,12 +77,16 @@ protected SamePackageProtectedCtor() { class SamePackageProtectedSerializable extends Serialize.SamePackageProtectedCtor implements Serializable { + private static final long serialVersionUID = 1L; + SamePackageProtectedSerializable() { } }; class SamePackagePrivateCtor { + private static final long serialVersionUID = 1L; + private SamePackagePrivateCtor() { } public SamePackagePrivateCtor(int l) { @@ -82,6 +96,8 @@ public SamePackagePrivateCtor(int l) { class SamePackagePrivateSerializable extends Serialize.SamePackagePrivateCtor implements Serializable { + private static final long serialVersionUID = 1L; + SamePackagePrivateSerializable() { super(1); } @@ -90,6 +106,8 @@ class SamePackagePrivateSerializable class PrivateSerializable extends NonSerializable.PrivateCtor implements Serializable { + private static final long serialVersionUID = 1L; + int field1 = 5; PrivateSerializable() { @@ -98,6 +116,8 @@ class PrivateSerializable }; class ExternalizablePublicCtor implements Externalizable { + private static final long serialVersionUID = 1L; + public ExternalizablePublicCtor() { } public void writeExternal(ObjectOutput out) throws IOException { @@ -108,7 +128,10 @@ public void readExternal(ObjectInput in) } }; +@SuppressWarnings("serial") /* Incorrect declarations are being tested */ class ExternalizableProtectedCtor implements Externalizable { + private static final long serialVersionUID = 1L; + protected ExternalizableProtectedCtor() { } public void writeExternal(ObjectOutput out) throws IOException { @@ -119,7 +142,10 @@ public void readExternal(ObjectInput in) } }; +@SuppressWarnings("serial") /* Incorrect declarations are being tested */ class ExternalizablePackageCtor implements Externalizable { + private static final long serialVersionUID = 1L; + ExternalizablePackageCtor() { } public void writeExternal(ObjectOutput out) throws IOException { @@ -130,7 +156,10 @@ public void readExternal(ObjectInput in) } }; +@SuppressWarnings("serial") /* Incorrect declarations are being tested */ class ExternalizablePrivateCtor implements Externalizable { + private static final long serialVersionUID = 1L; + private ExternalizablePrivateCtor() { } public ExternalizablePrivateCtor(int i) { diff --git a/test/jdk/java/io/Serializable/NPEProvoker/NPEProvoker.java b/test/jdk/java/io/Serializable/NPEProvoker/NPEProvoker.java index 15981432a67..119ff6e04fc 100644 --- a/test/jdk/java/io/Serializable/NPEProvoker/NPEProvoker.java +++ b/test/jdk/java/io/Serializable/NPEProvoker/NPEProvoker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -41,6 +41,8 @@ import java.util.ArrayList; public class NPEProvoker implements java.io.Externalizable { + private static final long serialVersionUID = 1L; + private String test = "test"; public void readExternal(ObjectInput in) throws IOException, diff --git a/test/jdk/java/io/Serializable/NoClassDefFoundErrorTrap/NoClassDefFoundErrorTrap.java b/test/jdk/java/io/Serializable/NoClassDefFoundErrorTrap/NoClassDefFoundErrorTrap.java index da9a2a6cca4..c2c05faad61 100644 --- a/test/jdk/java/io/Serializable/NoClassDefFoundErrorTrap/NoClassDefFoundErrorTrap.java +++ b/test/jdk/java/io/Serializable/NoClassDefFoundErrorTrap/NoClassDefFoundErrorTrap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,9 @@ public class NoClassDefFoundErrorTrap { private static NoClassDefFoundError ncdfe; public interface Bar {} - public static class Foo implements Bar, java.io.Serializable {} + public static class Foo implements Bar, java.io.Serializable { + private static final long serialVersionUID = 1L; + } /** * Test subclass of ObjectInputStream that overrides resolveClass @@ -55,7 +57,7 @@ public TestObjectInputStream(InputStream in) super(in); } - protected Class resolveClass(ObjectStreamClass desc) + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); diff --git a/test/jdk/java/io/Serializable/PutField/Write2.java b/test/jdk/java/io/Serializable/PutField/Write2.java index c30554ad06b..f915b52402f 100644 --- a/test/jdk/java/io/Serializable/PutField/Write2.java +++ b/test/jdk/java/io/Serializable/PutField/Write2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ class Foo implements Serializable { new ObjectStreamField("s2", String.class) }; + @SuppressWarnings("deprecation") private void writeObject(ObjectOutputStream out) throws IOException { ObjectOutputStream.PutField fields = out.putFields(); fields.put("s1", "qwerty"); diff --git a/test/jdk/java/io/Serializable/badSerialPersistentField/BadSerialPersistentField.java b/test/jdk/java/io/Serializable/badSerialPersistentField/BadSerialPersistentField.java index c8cb87831a7..68040d1302d 100644 --- a/test/jdk/java/io/Serializable/badSerialPersistentField/BadSerialPersistentField.java +++ b/test/jdk/java/io/Serializable/badSerialPersistentField/BadSerialPersistentField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,12 +31,16 @@ import java.io.*; class A implements Serializable { + private static final long serialVersionUID = 1L; + private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("nonexistent", int.class) }; } class B implements Serializable { + private static final long serialVersionUID = 1L; + private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("mismatched", int.class) }; @@ -44,6 +48,8 @@ class B implements Serializable { } class C implements Serializable { + private static final long serialVersionUID = 1L; + private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("existent", int.class) }; diff --git a/test/jdk/java/io/Serializable/badSerialVersionUID/BadSerialVersionUID.java b/test/jdk/java/io/Serializable/badSerialVersionUID/BadSerialVersionUID.java index d06a5da265f..0897aa74e80 100644 --- a/test/jdk/java/io/Serializable/badSerialVersionUID/BadSerialVersionUID.java +++ b/test/jdk/java/io/Serializable/badSerialVersionUID/BadSerialVersionUID.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,42 +32,50 @@ import java.io.*; class Z implements Serializable { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final boolean serialVersionUID = false; } class B implements Serializable { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final byte serialVersionUID = 5; } class C implements Serializable { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final char serialVersionUID = 5; } class S implements Serializable { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final short serialVersionUID = 5; } class I implements Serializable { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final int serialVersionUID = 5; } class F implements Serializable { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final float serialVersionUID = 5.0F; } class D implements Serializable { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final double serialVersionUID = 5.0; } class L implements Serializable { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final Object serialVersionUID = "5"; } public class BadSerialVersionUID { public static void main(String[] args) throws Exception { - Class[] ignore = { Z.class, F.class, D.class, L.class }; - Class[] convert = { B.class, C.class, S.class, I.class }; + Class[] ignore = { Z.class, F.class, D.class, L.class }; + Class[] convert = { B.class, C.class, S.class, I.class }; for (int i = 0; i < ignore.length; i++) { ObjectStreamClass.lookup(ignore[i]).getSerialVersionUID(); diff --git a/test/jdk/java/io/Serializable/badSubstByReplace/BadSubstByReplace.java b/test/jdk/java/io/Serializable/badSubstByReplace/BadSubstByReplace.java index a943df1f913..bd81e71ea79 100644 --- a/test/jdk/java/io/Serializable/badSubstByReplace/BadSubstByReplace.java +++ b/test/jdk/java/io/Serializable/badSubstByReplace/BadSubstByReplace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,11 +29,16 @@ */ import java.io.*; -class A implements Serializable {} +class A implements Serializable { + private static final long serialVersionUID = 1L; +} -class B implements Serializable {} +class B implements Serializable { + private static final long serialVersionUID = 1L; +} class Container implements Serializable { + private static final long serialVersionUID = 1L; A a = new A(); } diff --git a/test/jdk/java/io/Serializable/checkModifiers/CheckModifiers.java b/test/jdk/java/io/Serializable/checkModifiers/CheckModifiers.java index c3bd779f3aa..614c3cd1935 100644 --- a/test/jdk/java/io/Serializable/checkModifiers/CheckModifiers.java +++ b/test/jdk/java/io/Serializable/checkModifiers/CheckModifiers.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,10 @@ import java.io.*; class TestClass1 implements Serializable { + private static final long serialVersionUID = 1L; + // Missing the "final" modifier + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("field1", Integer.class), new ObjectStreamField("field2", Double.TYPE), @@ -58,7 +61,7 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ObjectInputStream.GetField pfields = ois.readFields(); - field1 = (Integer) pfields.get("field1", new Integer(100)); + field1 = (Integer) pfields.get("field1", Integer.valueOf(100)); field2 = pfields.get("field2", 99.99); /* These fields must be present in the stream */ @@ -79,7 +82,10 @@ private void readObject(ObjectInputStream ois) class TestClass2 implements Serializable { + private static final long serialVersionUID = 1L; + // public instead of private + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ public static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("field1", Integer.class), new ObjectStreamField("field2", Double.TYPE), @@ -101,7 +107,7 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ObjectInputStream.GetField pfields = ois.readFields(); - field1 = (Integer) pfields.get("field1", new Integer(100)); + field1 = (Integer) pfields.get("field1", Integer.valueOf(100)); field2 = pfields.get("field2", 99.99); /* These fields must be present in the stream */ @@ -121,7 +127,10 @@ private void readObject(ObjectInputStream ois) }; class TestClass3 implements Serializable{ + private static final long serialVersionUID = 1L; + // Not of type ObjectStreamField + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private final String[] serialPersistentFields = {"Foo","Foobar"};; Integer field1; double field2; @@ -139,7 +148,7 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ObjectInputStream.GetField pfields = ois.readFields(); - field1 = (Integer) pfields.get("field1", new Integer(100)); + field1 = (Integer) pfields.get("field1", Integer.valueOf(100)); field2 = pfields.get("field2", 99.99); field3 = pfields.get("field3", 99); field4 = (String) pfields.get("field4", "Default string"); @@ -156,6 +165,8 @@ private void readObject(ObjectInputStream ois) }; class TestClass4 implements Serializable { + private static final long serialVersionUID = 1L; + // Correct format private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("field1", Integer.class), @@ -178,7 +189,7 @@ private void readObject(ObjectInputStream ois) throws IOException, ClassNotFoundException { ObjectInputStream.GetField pfields = ois.readFields(); - field1 = (Integer) pfields.get("field1", new Integer(100)); + field1 = (Integer) pfields.get("field1", Integer.valueOf(100)); field2 = pfields.get("field2", 99.99); try { @@ -199,16 +210,16 @@ private void readObject(ObjectInputStream ois) public class CheckModifiers { public static void main(String[] args) throws ClassNotFoundException, IOException{ - TestClass1 tc1 = new TestClass1(new Integer(100), 25.56, 2000, + TestClass1 tc1 = new TestClass1(100, 25.56, 2000, new String("Test modifiers of serialPersistentFields")); - TestClass2 tc2 = new TestClass2(new Integer(100), 25.56, 2000, + TestClass2 tc2 = new TestClass2(100, 25.56, 2000, new String("Test modifiers of serialPersistentFields")); - TestClass3 tc3 = new TestClass3(new Integer(100), 25.56, 2000, + TestClass3 tc3 = new TestClass3(100, 25.56, 2000, new String("Test Type of serialPersistentFields")); - TestClass4 tc4 = new TestClass4(new Integer(100), 25.56, 2000, + TestClass4 tc4 = new TestClass4(100, 25.56, 2000, new String("Test modifiers of serialPersistentFields")); diff --git a/test/jdk/java/io/Serializable/class/SerialA_2/A.java b/test/jdk/java/io/Serializable/class/SerialA_2/A.java index 8fe4c784ebd..e8f81a86974 100644 --- a/test/jdk/java/io/Serializable/class/SerialA_2/A.java +++ b/test/jdk/java/io/Serializable/class/SerialA_2/A.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,7 +24,7 @@ import java.io.Serializable; public class A implements Serializable { - static final long serialVersionUID = 746945609796141988L; + private static final long serialVersionUID = 746945609796141988L; int field1; int field2; diff --git a/test/jdk/java/io/Serializable/classDescFlagConflict/Foo.java b/test/jdk/java/io/Serializable/classDescFlagConflict/Foo.java index 23627178387..74250305e5f 100644 --- a/test/jdk/java/io/Serializable/classDescFlagConflict/Foo.java +++ b/test/jdk/java/io/Serializable/classDescFlagConflict/Foo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ import java.io.*; public class Foo implements Externalizable { + private static final long serialVersionUID = 1L; + public void writeExternal(ObjectOutput out) throws IOException {} public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {} diff --git a/test/jdk/java/io/Serializable/classDescGetField/GetField.java b/test/jdk/java/io/Serializable/classDescGetField/GetField.java index dc2a43ef077..28e18a4af86 100644 --- a/test/jdk/java/io/Serializable/classDescGetField/GetField.java +++ b/test/jdk/java/io/Serializable/classDescGetField/GetField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,6 +33,8 @@ import java.io.*; public class GetField implements Serializable{ + private static final long serialVersionUID = 1L; + String str; int i; diff --git a/test/jdk/java/io/Serializable/classDescHooks/CNFException.java b/test/jdk/java/io/Serializable/classDescHooks/CNFException.java index d1944f32161..b0d65c351f7 100644 --- a/test/jdk/java/io/Serializable/classDescHooks/CNFException.java +++ b/test/jdk/java/io/Serializable/classDescHooks/CNFException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ public class CNFException { public static void main(String[] args) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(bout); - oout.writeObject(new Integer(5)); + oout.writeObject(5); oout.close(); ObjectInputStream oin = new CNFInputStream(new ByteArrayInputStream(bout.toByteArray())); diff --git a/test/jdk/java/io/Serializable/classDescHooks/ClassDescHooks.java b/test/jdk/java/io/Serializable/classDescHooks/ClassDescHooks.java index e31899e8479..6894768cf86 100644 --- a/test/jdk/java/io/Serializable/classDescHooks/ClassDescHooks.java +++ b/test/jdk/java/io/Serializable/classDescHooks/ClassDescHooks.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,9 +32,9 @@ class Foo implements Serializable { private static final long serialVersionUID = 1L; - Short s = new Short((short) 1); - Integer i = new Integer(2); - Long l = new Long(3); + Short s = (short) 1; + Integer i = 2; + Long l = 3L; public boolean equals(Object obj) { if (obj instanceof Foo) { @@ -43,6 +43,10 @@ public boolean equals(Object obj) { } return false; } + + public int hashCode() { + return i; + } } class CustomOutputStream extends ObjectOutputStream { diff --git a/test/jdk/java/io/Serializable/classDescHooks/ExternLoopback.java b/test/jdk/java/io/Serializable/classDescHooks/ExternLoopback.java index f0f22de5f02..234e7064cf1 100644 --- a/test/jdk/java/io/Serializable/classDescHooks/ExternLoopback.java +++ b/test/jdk/java/io/Serializable/classDescHooks/ExternLoopback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,9 +32,9 @@ import java.util.*; class LoopbackOutputStream extends ObjectOutputStream { - LinkedList descs; + LinkedList descs; - LoopbackOutputStream(OutputStream out, LinkedList descs) + LoopbackOutputStream(OutputStream out, LinkedList descs) throws IOException { super(out); @@ -49,9 +49,9 @@ protected void writeClassDescriptor(ObjectStreamClass desc) } class LoopbackInputStream extends ObjectInputStream { - LinkedList descs; + LinkedList descs; - LoopbackInputStream(InputStream in, LinkedList descs) throws IOException { + LoopbackInputStream(InputStream in, LinkedList descs) throws IOException { super(in); this.descs = descs; } @@ -59,11 +59,12 @@ class LoopbackInputStream extends ObjectInputStream { protected ObjectStreamClass readClassDescriptor() throws IOException, ClassNotFoundException { - return (ObjectStreamClass) descs.removeFirst(); + return descs.removeFirst(); } } public class ExternLoopback implements Externalizable { + private static final long serialVersionUID = 1L; String a, b, c; @@ -100,13 +101,17 @@ public boolean equals(Object obj) { return streq(a, other.a) && streq(b, other.b) && streq(c, other.c); } + public int hashCode() { + return a.hashCode(); + } + static boolean streq(String s1, String s2) { return (s1 != null) ? s1.equals(s2) : (s2 == null); } public static void main(String[] args) throws Exception { ExternLoopback lb = new ExternLoopback("foo", "bar", "baz"); - LinkedList descs = new LinkedList(); + LinkedList descs = new LinkedList<>(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); LoopbackOutputStream lout = new LoopbackOutputStream(bout, descs); lout.writeObject(lb); diff --git a/test/jdk/java/io/Serializable/classDescHooks/Loopback.java b/test/jdk/java/io/Serializable/classDescHooks/Loopback.java index 8f1d5a80353..83dc6cd2dae 100644 --- a/test/jdk/java/io/Serializable/classDescHooks/Loopback.java +++ b/test/jdk/java/io/Serializable/classDescHooks/Loopback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,9 +33,9 @@ import java.util.*; class LoopbackOutputStream extends ObjectOutputStream { - LinkedList descs; + LinkedList descs; - LoopbackOutputStream(OutputStream out, LinkedList descs) + LoopbackOutputStream(OutputStream out, LinkedList descs) throws IOException { super(out); @@ -50,21 +50,22 @@ protected void writeClassDescriptor(ObjectStreamClass desc) } class LoopbackInputStream extends ObjectInputStream { - LinkedList descs; + LinkedList descs; - LoopbackInputStream(InputStream in, LinkedList descs) throws IOException { + LoopbackInputStream(InputStream in, LinkedList descs) throws IOException { super(in); this.descs = descs; } protected ObjectStreamClass readClassDescriptor() - throws IOException, ClassNotFoundException { - return (ObjectStreamClass) descs.removeFirst(); + return descs.removeFirst(); } } public class Loopback implements Serializable { + private static final long serialVersionUID = 1L; + String str; Loopback(String str) { @@ -73,7 +74,7 @@ public class Loopback implements Serializable { public static void main(String[] args) throws Exception { Loopback lb = new Loopback("foo"); - LinkedList descs = new LinkedList(); + LinkedList descs = new LinkedList<>(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); LoopbackOutputStream lout = new LoopbackOutputStream(bout, descs); lout.writeObject(lb); diff --git a/test/jdk/java/io/Serializable/cloneArray/CloneArray.java b/test/jdk/java/io/Serializable/cloneArray/CloneArray.java index 650ac3ccb9f..a8de4407912 100644 --- a/test/jdk/java/io/Serializable/cloneArray/CloneArray.java +++ b/test/jdk/java/io/Serializable/cloneArray/CloneArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,6 +40,8 @@ public class CloneArray { static Object replacement; static class Resolver implements Serializable { + private static final long serialVersionUID = 1L; + private Object readResolve() throws ObjectStreamException { return replacement; } diff --git a/test/jdk/java/io/Serializable/concurrentClassDescLookup/ConcurrentClassDescLookup.java b/test/jdk/java/io/Serializable/concurrentClassDescLookup/ConcurrentClassDescLookup.java index 039c768b087..196a27b52ba 100644 --- a/test/jdk/java/io/Serializable/concurrentClassDescLookup/ConcurrentClassDescLookup.java +++ b/test/jdk/java/io/Serializable/concurrentClassDescLookup/ConcurrentClassDescLookup.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2024, 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 @@ -28,8 +28,11 @@ */ import java.io.*; +import java.util.concurrent.CountDownLatch; class Good implements Serializable { + private static final long serialVersionUID = 6319710844400051132L; + static { try { Thread.sleep(1000); } catch (InterruptedException ex) {} } @@ -47,21 +50,22 @@ class Bad implements Serializable { } class SuccessfulLookup extends Thread { - Class cl; + Class cl; long suid; - Object barrier; + final CountDownLatch lookupLatch; boolean ok; - SuccessfulLookup(Class cl, long suid, Object barrier) { + SuccessfulLookup(Class cl, long suid, CountDownLatch lookupLatch) { this.cl = cl; this.suid = suid; - this.barrier = barrier; + this.lookupLatch = lookupLatch; } public void run() { - synchronized (barrier) { - try { barrier.wait(); } catch (InterruptedException ex) {} - } + lookupLatch.countDown(); // let others know we are ready + try { + lookupLatch.await(); // await for others + } catch (InterruptedException ex) {} for (int i = 0; i < 100; i++) { if (ObjectStreamClass.lookup(cl).getSerialVersionUID() != suid) { return; @@ -72,19 +76,20 @@ public void run() { } class FailingLookup extends Thread { - Class cl; - Object barrier; + Class cl; + final CountDownLatch lookupLatch; boolean ok; - FailingLookup(Class cl, Object barrier) { + FailingLookup(Class cl, CountDownLatch lookupLatch) { this.cl = cl; - this.barrier = barrier; + this.lookupLatch = lookupLatch; } public void run() { - synchronized (barrier) { - try { barrier.wait(); } catch (InterruptedException ex) {} - } + lookupLatch.countDown(); // let others know we are ready + try { + lookupLatch.await(); // await for others + } catch (InterruptedException ex) {} for (int i = 0; i < 100; i++) { try { ObjectStreamClass.lookup(cl); @@ -99,40 +104,37 @@ public void run() { public class ConcurrentClassDescLookup { public static void main(String[] args) throws Exception { ClassLoader loader = ConcurrentClassDescLookup.class.getClassLoader(); - Class cl = Class.forName("Good", false, loader); - Object barrier = new Object(); - SuccessfulLookup[] slookups = new SuccessfulLookup[50]; + Class cl = Class.forName("Good", false, loader); + int numSuccessfulLookups = 50; + CountDownLatch sLookupLatch = new CountDownLatch(numSuccessfulLookups); + SuccessfulLookup[] slookups = new SuccessfulLookup[numSuccessfulLookups]; for (int i = 0; i < slookups.length; i++) { - slookups[i] = - new SuccessfulLookup(cl, 6319710844400051132L, barrier); + slookups[i] = new SuccessfulLookup(cl, 6319710844400051132L, sLookupLatch); slookups[i].start(); } - Thread.sleep(1000); - synchronized (barrier) { - barrier.notifyAll(); - } + System.out.println("awaiting completion of " + slookups.length + " SuccessfulLookup"); for (int i = 0; i < slookups.length; i++) { slookups[i].join(); if (!slookups[i].ok) { throw new Error(); } } - + System.out.println("all " + slookups.length + " SuccessfulLookup completed"); cl = Class.forName("Bad", false, loader); - FailingLookup[] flookups = new FailingLookup[50]; + int numFailingLookups = 50; + CountDownLatch fLookupLatch = new CountDownLatch(numFailingLookups); + FailingLookup[] flookups = new FailingLookup[numFailingLookups]; for (int i = 0; i < flookups.length; i++) { - flookups[i] = new FailingLookup(cl, barrier); + flookups[i] = new FailingLookup(cl, fLookupLatch); flookups[i].start(); } - Thread.sleep(1000); - synchronized (barrier) { - barrier.notifyAll(); - } - for (int i = 0; i < slookups.length; i++) { + System.out.println("awaiting completion of " + flookups.length + " FailingLookup"); + for (int i = 0; i < flookups.length; i++) { flookups[i].join(); if (!flookups[i].ok) { throw new Error(); } } + System.out.println("all " + flookups.length + " FailingLookup completed"); } } diff --git a/test/jdk/java/io/Serializable/defaultDataEnd/DefaultDataEnd.java b/test/jdk/java/io/Serializable/defaultDataEnd/DefaultDataEnd.java index 69fecfaacf6..eabb332c6d1 100644 --- a/test/jdk/java/io/Serializable/defaultDataEnd/DefaultDataEnd.java +++ b/test/jdk/java/io/Serializable/defaultDataEnd/DefaultDataEnd.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ import java.io.*; class A implements Serializable { + private static final long serialVersionUID = 1L; + int i1 = 1, i2 = 2; String s1 = "foo", s2 = "bar"; @@ -66,6 +68,8 @@ private void readObject(ObjectInputStream in) } class B implements Serializable { + private static final long serialVersionUID = 1L; + int i1 = 1, i2 = 2; String s1 = "foo", s2 = "bar"; @@ -101,6 +105,8 @@ private void readObject(ObjectInputStream in) } class C implements Serializable { + private static final long serialVersionUID = 1L; + private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { diff --git a/test/jdk/java/io/Serializable/defaultReadObjectCNFException/DefaultReadObjectCNFException.java b/test/jdk/java/io/Serializable/defaultReadObjectCNFException/DefaultReadObjectCNFException.java index b345ddc72e0..0550c8fb267 100644 --- a/test/jdk/java/io/Serializable/defaultReadObjectCNFException/DefaultReadObjectCNFException.java +++ b/test/jdk/java/io/Serializable/defaultReadObjectCNFException/DefaultReadObjectCNFException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,9 @@ import java.io.*; class Foo implements Serializable { + private static final long serialVersionUID = 1L; + + @SuppressWarnings("serial") /* Incorrect use is being tested */ Object obj = new Bar(); private void readObject(ObjectInputStream in) @@ -44,12 +47,14 @@ private void readObject(ObjectInputStream in) } } -class Bar implements Serializable {} +class Bar implements Serializable { + private static final long serialVersionUID = 1L; +} class TestObjectInputStream extends ObjectInputStream { TestObjectInputStream(InputStream in) throws IOException { super(in); } - protected Class resolveClass(ObjectStreamClass desc) + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { if (desc.getName().equals(Bar.class.getName())) { diff --git a/test/jdk/java/io/Serializable/defaulted/GetFieldRead.java b/test/jdk/java/io/Serializable/defaulted/GetFieldRead.java index 3e3ab29fcad..a7f27177333 100644 --- a/test/jdk/java/io/Serializable/defaulted/GetFieldRead.java +++ b/test/jdk/java/io/Serializable/defaulted/GetFieldRead.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,9 +30,9 @@ import java.io.*; class TestClass implements Serializable { - public static final Integer DEFAULT_OBJECT_I = new Integer(99); + public static final Integer DEFAULT_OBJECT_I = 99; public static final Foo DEFAULT_OBJECT_F = new Foo(); - private static final long serialVersionUID=5748652654655279289L; + private static final long serialVersionUID = 5748652654655279289L; // Fields to be serialized. private static final ObjectStreamField[] serialPersistentFields = { diff --git a/test/jdk/java/io/Serializable/defaulted/GetFieldWrite.java b/test/jdk/java/io/Serializable/defaulted/GetFieldWrite.java index 6fe3740cd4f..cb11db450f7 100644 --- a/test/jdk/java/io/Serializable/defaulted/GetFieldWrite.java +++ b/test/jdk/java/io/Serializable/defaulted/GetFieldWrite.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,8 +62,7 @@ public static void main(String[] args) { FileOutputStream fos = new FileOutputStream("data.ser"); ObjectOutput out = new ObjectOutputStream(fos); - out.writeObject(new TestClass(new Foo(100, 200), new Integer(100), - 200)); + out.writeObject(new TestClass(new Foo(100, 200), 100, 200)); out.close(); } }; @@ -72,6 +71,8 @@ public static void main(String[] args) * Test class to be used as data field */ class Foo implements Serializable{ + private static final long serialVersionUID = 1L; + int a; int b; public Foo() { diff --git a/test/jdk/java/io/Serializable/enum/classObject/Test.java b/test/jdk/java/io/Serializable/enum/classObject/Test.java index 3c98c99edcb..ed8ed231706 100644 --- a/test/jdk/java/io/Serializable/enum/classObject/Test.java +++ b/test/jdk/java/io/Serializable/enum/classObject/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,7 +35,7 @@ public class Test { public static void main(String[] args) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(bout); - Class[] classes = { Enum.class, Foo.foo.getClass(), + Class[] classes = { Enum.class, Foo.foo.getClass(), Foo.bar.getClass(), Foo.baz.getClass() }; for (int i = 0; i < classes.length; i++) { oout.writeObject(classes[i]); diff --git a/test/jdk/java/io/Serializable/enum/ignoreSerializationFields/Test.java b/test/jdk/java/io/Serializable/enum/ignoreSerializationFields/Test.java index 602e2a4fa30..e543aaf40af 100644 --- a/test/jdk/java/io/Serializable/enum/ignoreSerializationFields/Test.java +++ b/test/jdk/java/io/Serializable/enum/ignoreSerializationFields/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ enum Foo { foo, bar { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final long serialVersionUID = 2L; // bar is implemented as an inner class instance, so the following // declaration would cause a compile-time error @@ -42,7 +43,10 @@ enum Foo { // }; }; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final long serialVersionUID = 1L; + + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("blargh", Integer.TYPE) }; @@ -50,7 +54,7 @@ enum Foo { public class Test { public static void main(String[] args) throws Exception { - Class[] classes = + Class[] classes = { Foo.class, Foo.foo.getClass(), Foo.bar.getClass() }; for (int i = 0; i < classes.length; i++) { ObjectStreamClass desc = ObjectStreamClass.lookup(classes[i]); diff --git a/test/jdk/java/io/Serializable/enum/ignoreSerializationMethods/Test.java b/test/jdk/java/io/Serializable/enum/ignoreSerializationMethods/Test.java index 785b815172f..cbbf87c7397 100644 --- a/test/jdk/java/io/Serializable/enum/ignoreSerializationMethods/Test.java +++ b/test/jdk/java/io/Serializable/enum/ignoreSerializationMethods/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,14 +33,17 @@ enum Foo { foo, bar { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private void writeObject(ObjectOutputStream out) throws IOException { throw new Error("bar.writeObject invoked"); } + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new Error("bar.readObject invoked"); } + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ Object writeReplace() throws ObjectStreamException { throw new Error("bar.writeReplace invoked"); } @@ -50,14 +53,17 @@ Object writeReplace() throws ObjectStreamException { // } }; + @SuppressWarnings("serial") /* Incorrect use is being tested */ private void writeObject(ObjectOutputStream out) throws IOException { throw new Error("Foo.writeObject invoked"); } + @SuppressWarnings("serial") /* Incorrect use is being tested */ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { throw new Error("Foo.readObject invoked"); } + @SuppressWarnings("serial") /* Incorrect use is being tested */ Object writeReplace() throws ObjectStreamException { throw new Error("Foo.writeReplace invoked"); } diff --git a/test/jdk/java/io/Serializable/enum/mismatchedTypecode/Test.java b/test/jdk/java/io/Serializable/enum/mismatchedTypecode/Test.java index 1823098f585..61ad4d58e3f 100644 --- a/test/jdk/java/io/Serializable/enum/mismatchedTypecode/Test.java +++ b/test/jdk/java/io/Serializable/enum/mismatchedTypecode/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -71,7 +71,7 @@ public static void main(String[] args) throws Exception { } oout = new TestObjectOutputStream(bout = new ByteArrayOutputStream()); - oout.writeObject(new Integer(5)); + oout.writeObject(5); oout.close(); oin = new ObjectInputStream( new ByteArrayInputStream(bout.toByteArray())); diff --git a/test/jdk/java/io/Serializable/evolution/AddedExternField/ReadAddedField.java b/test/jdk/java/io/Serializable/evolution/AddedExternField/ReadAddedField.java index ce54293f65c..f871693b172 100644 --- a/test/jdk/java/io/Serializable/evolution/AddedExternField/ReadAddedField.java +++ b/test/jdk/java/io/Serializable/evolution/AddedExternField/ReadAddedField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,8 @@ class A implements Serializable { } class D implements Serializable { + private static final long serialVersionUID = 1L; + public int x; D(int y) { x = y; diff --git a/test/jdk/java/io/Serializable/evolution/AddedExternField/WriteAddedField.java b/test/jdk/java/io/Serializable/evolution/AddedExternField/WriteAddedField.java index 821533e47a5..e8677d3eb10 100644 --- a/test/jdk/java/io/Serializable/evolution/AddedExternField/WriteAddedField.java +++ b/test/jdk/java/io/Serializable/evolution/AddedExternField/WriteAddedField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,6 +36,8 @@ import java.io.*; class NewExternFieldClass implements Externalizable { + private static final long serialVersionUID = 1L; + byte l; public NewExternFieldClass() { @@ -60,6 +62,8 @@ public void writeExternal(ObjectOutput s) throws IOException } class D implements Serializable { + private static final long serialVersionUID = 1L; + public int x; D(int y) { x = y; diff --git a/test/jdk/java/io/Serializable/evolution/AddedField/ReadAddedField.java b/test/jdk/java/io/Serializable/evolution/AddedField/ReadAddedField.java index d9e63b021dc..648329a79e2 100644 --- a/test/jdk/java/io/Serializable/evolution/AddedField/ReadAddedField.java +++ b/test/jdk/java/io/Serializable/evolution/AddedField/ReadAddedField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,7 @@ import java.io.*; class IncompatibleFieldClass implements Serializable { - private static long serialVersionUID = 4L; + private static final long serialVersionUID = 3L; int x = 5; }; diff --git a/test/jdk/java/io/Serializable/evolution/AddedField/WriteAddedField.java b/test/jdk/java/io/Serializable/evolution/AddedField/WriteAddedField.java index 63a45a419bf..b188f5d6928 100644 --- a/test/jdk/java/io/Serializable/evolution/AddedField/WriteAddedField.java +++ b/test/jdk/java/io/Serializable/evolution/AddedField/WriteAddedField.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,8 @@ import java.io.*; class NewFieldClass implements Serializable { + private static final long serialVersionUID = 1L; + int k; NewFieldClass(int value) { @@ -45,11 +47,14 @@ class NewFieldClass implements Serializable { }; class IncompatibleFieldClass implements Serializable { - private static long serialVersionUID = 3L; + private static final long serialVersionUID = 3L; int x = 5; }; +@SuppressWarnings("serial") /* Incorrect use is being tested */ class NewExternFieldClass implements Externalizable { + private static final long serialVersionUID = 1L; + byte l; public NewExternFieldClass(int value) { diff --git a/test/jdk/java/io/Serializable/evolution/AddedSuperClass/ReadAddedSuperClass2.java b/test/jdk/java/io/Serializable/evolution/AddedSuperClass/ReadAddedSuperClass2.java index 60c50a2ecea..5559e9e1346 100644 --- a/test/jdk/java/io/Serializable/evolution/AddedSuperClass/ReadAddedSuperClass2.java +++ b/test/jdk/java/io/Serializable/evolution/AddedSuperClass/ReadAddedSuperClass2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,8 @@ import java.io.*; class AddedSuperClass implements Serializable { + private static final long serialVersionUID = 1L; + // Needed at least one field to recreate failure. int field; } diff --git a/test/jdk/java/io/Serializable/evolution/AddedSuperClass/WriteAddedSuperClass.java b/test/jdk/java/io/Serializable/evolution/AddedSuperClass/WriteAddedSuperClass.java index 96fde23c42e..e15b20e2784 100644 --- a/test/jdk/java/io/Serializable/evolution/AddedSuperClass/WriteAddedSuperClass.java +++ b/test/jdk/java/io/Serializable/evolution/AddedSuperClass/WriteAddedSuperClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,8 @@ import java.io.*; class AddedSuperClass implements Serializable { + private static final long serialVersionUID = 1L; + // Needed at least one field to recreate failure. int field; } diff --git a/test/jdk/java/io/Serializable/expectedStackTrace/ExpectedStackTrace.java b/test/jdk/java/io/Serializable/expectedStackTrace/ExpectedStackTrace.java index 3021ba90d26..ad18d02697d 100644 --- a/test/jdk/java/io/Serializable/expectedStackTrace/ExpectedStackTrace.java +++ b/test/jdk/java/io/Serializable/expectedStackTrace/ExpectedStackTrace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,9 +42,11 @@ public NotSerializableObject(String m_str, Integer m_int) { } } +@SuppressWarnings("serial") /* Incorrect declarations are being tested */ class SerializableObject extends NotSerializableObject implements Serializable { + private static final long serialVersionUID = 1L; public SerializableObject(String m_str, Integer m_int) { super(m_str, m_int); @@ -67,7 +69,7 @@ private static Object getObject() throws Exception { ObjectStreamClass osc = ObjectStreamClass.lookup(SerializableObject.class); SerializableObject initObj = - (SerializableObject) osc.forClass().newInstance(); + (SerializableObject) osc.forClass().getConstructor().newInstance(); return initObj; } diff --git a/test/jdk/java/io/Serializable/explicitCNFException/ExplicitCNFException.java b/test/jdk/java/io/Serializable/explicitCNFException/ExplicitCNFException.java index fcc3a9ceddc..c69046cf65d 100644 --- a/test/jdk/java/io/Serializable/explicitCNFException/ExplicitCNFException.java +++ b/test/jdk/java/io/Serializable/explicitCNFException/ExplicitCNFException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ import java.io.*; class A implements Serializable { + private static final long serialVersionUID = 1L; + private void readObject(ObjectInputStream in) throws ClassNotFoundException, IOException { @@ -39,6 +41,8 @@ private void readObject(ObjectInputStream in) } class B implements Externalizable { + private static final long serialVersionUID = 1L; + public B() {} public void writeExternal(ObjectOutput out) throws IOException {} diff --git a/test/jdk/java/io/Serializable/failureAtomicity/Bar.template b/test/jdk/java/io/Serializable/failureAtomicity/Bar.template index 465bc2b5e8b..6e45dd69809 100644 --- a/test/jdk/java/io/Serializable/failureAtomicity/Bar.template +++ b/test/jdk/java/io/Serializable/failureAtomicity/Bar.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ import java.io.Serializable; import failureAtomicity.SerialRef; public class Bar extends Foo implements Serializable { - static final long serialVersionUID = -0L; + private static final long serialVersionUID = -0L; public final long barPrim; public final String barRef; diff --git a/test/jdk/java/io/Serializable/failureAtomicity/Foo.template b/test/jdk/java/io/Serializable/failureAtomicity/Foo.template index 455d34c9a29..a1676b052c6 100644 --- a/test/jdk/java/io/Serializable/failureAtomicity/Foo.template +++ b/test/jdk/java/io/Serializable/failureAtomicity/Foo.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -28,7 +28,7 @@ import java.io.Serializable; import failureAtomicity.SerialRef; public class Foo implements Serializable { - static final long serialVersionUID = -0L; + private static final long serialVersionUID = -0L; public final int fooPrim; public final String fooRef; diff --git a/test/jdk/java/io/Serializable/failureAtomicity/SerialRef.java b/test/jdk/java/io/Serializable/failureAtomicity/SerialRef.java index 68317dfc293..443d2551c69 100644 --- a/test/jdk/java/io/Serializable/failureAtomicity/SerialRef.java +++ b/test/jdk/java/io/Serializable/failureAtomicity/SerialRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,9 +30,10 @@ // For verification purposes only. public class SerialRef implements Serializable { - static final long serialVersionUID = -0L; + private static final long serialVersionUID = -0L; public static Object obj; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private final Object ref; public SerialRef(Object ref) { diff --git a/test/jdk/java/io/Serializable/fieldTypeString/Write.java b/test/jdk/java/io/Serializable/fieldTypeString/Write.java index 00d71a51160..4a22f066a3a 100644 --- a/test/jdk/java/io/Serializable/fieldTypeString/Write.java +++ b/test/jdk/java/io/Serializable/fieldTypeString/Write.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,7 @@ class Foo implements Serializable { private static final long serialVersionUID = 0L; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ Object obj; Foo(Object obj) { @@ -59,7 +60,7 @@ public static void main(String[] args) throws Exception { ObjectOutputStream oout = new ObjectOutputStream(new FileOutputStream("foo.ser")); oout.writeObject(new Foo("foo")); - oout.writeObject(new Foo(new Integer(0))); + oout.writeObject(new Foo(0)); oout.close(); oout = new ObjectOutputStream(new FileOutputStream("bar.ser")); diff --git a/test/jdk/java/io/Serializable/finalFields/FinalFields.java b/test/jdk/java/io/Serializable/finalFields/FinalFields.java index 7273a6952af..045e548d186 100644 --- a/test/jdk/java/io/Serializable/finalFields/FinalFields.java +++ b/test/jdk/java/io/Serializable/finalFields/FinalFields.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ import java.io.*; class Foo implements Serializable { + private static final long serialVersionUID = 1L; + final int i; Foo(int i) { @@ -41,6 +43,10 @@ public boolean equals(Object obj) { Foo f = (Foo) obj; return (i == f.i); } + + public int hashCode() { + return i; + } } public class FinalFields { @@ -68,4 +74,5 @@ public static void main(String[] args) throws Exception { if (! (f1.equals(f1copy) && f2.equals(f2copy))) throw new Error("copies don't match originals"); } + } diff --git a/test/jdk/java/io/Serializable/getSuidClinitError/GetSuidClinitError.java b/test/jdk/java/io/Serializable/getSuidClinitError/GetSuidClinitError.java index a6c0669fa86..cbaf63bd6b0 100644 --- a/test/jdk/java/io/Serializable/getSuidClinitError/GetSuidClinitError.java +++ b/test/jdk/java/io/Serializable/getSuidClinitError/GetSuidClinitError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.io.*; +@SuppressWarnings("serial") /* Incorrect declarations are being tested. */ class A implements Serializable { static { // compiler prohibits direct throw @@ -41,30 +42,36 @@ static void throwMe(RuntimeException ex) throws RuntimeException { } } +@SuppressWarnings("serial") /* Incorrect declarations are being tested. */ class B implements Serializable { } +@SuppressWarnings("serial") /* Incorrect declarations are being tested. */ class C implements Serializable { static { System.out.println("C."); } } +@SuppressWarnings("serial") /* Incorrect declarations are being tested. */ class B1 extends B { } +@SuppressWarnings("serial") /* Incorrect declarations are being tested. */ class B2 extends B { static { System.out.println("B2."); } } +@SuppressWarnings("serial") /* Incorrect declarations are being tested. */ class C1 extends C { } +@SuppressWarnings("serial") /* Incorrect declarations are being tested. */ class C2 extends C { static { System.out.println("C2."); } } public class GetSuidClinitError { public static void main(String[] args) throws Exception { - Class cl = Class.forName( + Class cl = Class.forName( "A", false, GetSuidClinitError.class.getClassLoader()); for (int i = 0; i < 2; i++) { try { @@ -83,7 +90,7 @@ public static void main(String[] args) throws Exception { } } - Class[] cls = new Class[] { + Class[] cls = { B.class, B1.class, B2.class, C.class, C1.class, C2.class }; diff --git a/test/jdk/java/io/Serializable/lookupInterfaceDesc/LookupInterfaceDesc.java b/test/jdk/java/io/Serializable/lookupInterfaceDesc/LookupInterfaceDesc.java index c425b2f3d7d..7d342e1825e 100644 --- a/test/jdk/java/io/Serializable/lookupInterfaceDesc/LookupInterfaceDesc.java +++ b/test/jdk/java/io/Serializable/lookupInterfaceDesc/LookupInterfaceDesc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,10 +30,12 @@ import java.io.*; interface Foo extends Serializable { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ static final long serialVersionUID = 0xCAFE; } interface Bar extends Externalizable { + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ static final long serialVersionUID = 0xBABE; } diff --git a/test/jdk/java/io/Serializable/misplacedArrayClassDesc/MisplacedArrayClassDesc.java b/test/jdk/java/io/Serializable/misplacedArrayClassDesc/MisplacedArrayClassDesc.java index 910567a6793..dd07d5e4ef2 100644 --- a/test/jdk/java/io/Serializable/misplacedArrayClassDesc/MisplacedArrayClassDesc.java +++ b/test/jdk/java/io/Serializable/misplacedArrayClassDesc/MisplacedArrayClassDesc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ import java.io.*; class TestArray implements Serializable { + private static final long serialVersionUID = 1L; + // size of array private static final int ARR_SIZE = 5; // serializable field diff --git a/test/jdk/java/io/Serializable/modifyStaticFields/ModifyStaticFields.java b/test/jdk/java/io/Serializable/modifyStaticFields/ModifyStaticFields.java index 0a16fc15842..a7b019fc236 100644 --- a/test/jdk/java/io/Serializable/modifyStaticFields/ModifyStaticFields.java +++ b/test/jdk/java/io/Serializable/modifyStaticFields/ModifyStaticFields.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ import java.io.*; public class ModifyStaticFields implements Serializable { + private static final long serialVersionUID = 1L; + private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[] { new ObjectStreamField("str", String.class) }; diff --git a/test/jdk/java/io/Serializable/nestedReplace/NestedReplace.java b/test/jdk/java/io/Serializable/nestedReplace/NestedReplace.java index 25619169ac8..d5b7ce549be 100644 --- a/test/jdk/java/io/Serializable/nestedReplace/NestedReplace.java +++ b/test/jdk/java/io/Serializable/nestedReplace/NestedReplace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,18 +35,23 @@ import java.io.*; class A implements Serializable { + private static final long serialVersionUID = 1L; + Object writeReplace() throws ObjectStreamException { return new B(); } } class B implements Serializable { + private static final long serialVersionUID = 1L; + Object writeReplace() throws ObjectStreamException { return new C(); } } class C implements Serializable { + private static final long serialVersionUID = 1L; static int writeReplaceCalled = 0; @@ -61,6 +66,8 @@ Object readResolve() throws ObjectStreamException { } class D implements Serializable { + private static final long serialVersionUID = 1L; + Object readResolve() throws ObjectStreamException { throw new Error("readResolve() called more than once"); } diff --git a/test/jdk/java/io/Serializable/noSuchFieldClarification/NoSuchFieldClarification.java b/test/jdk/java/io/Serializable/noSuchFieldClarification/NoSuchFieldClarification.java index 04bc18bb780..87d2f8c8f5e 100644 --- a/test/jdk/java/io/Serializable/noSuchFieldClarification/NoSuchFieldClarification.java +++ b/test/jdk/java/io/Serializable/noSuchFieldClarification/NoSuchFieldClarification.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,8 +33,9 @@ import java.io.*; class TwoDPoint implements Serializable { + private static final long serialVersionUID = 1L; - private double radius; + private double radius; private double angle; private static final ObjectStreamField[] serialPersistentFields = { diff --git a/test/jdk/java/io/Serializable/notAvailable/NotAvailable.java b/test/jdk/java/io/Serializable/notAvailable/NotAvailable.java index 0d3e395c7f4..3a8810b408b 100644 --- a/test/jdk/java/io/Serializable/notAvailable/NotAvailable.java +++ b/test/jdk/java/io/Serializable/notAvailable/NotAvailable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -76,6 +76,8 @@ public int available() { } class Class1 implements Serializable { + private static final long serialVersionUID = 1L; + int a, b; public Class1(int aa, int bb) { diff --git a/test/jdk/java/io/Serializable/oldTests/AnnotateClass.java b/test/jdk/java/io/Serializable/oldTests/AnnotateClass.java index 5290018e218..8f2471f9f4d 100644 --- a/test/jdk/java/io/Serializable/oldTests/AnnotateClass.java +++ b/test/jdk/java/io/Serializable/oldTests/AnnotateClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -102,7 +102,7 @@ class TestOutputStream extends ObjectOutputStream { /* When any class is written, add a "magic" string * that must be verified by the TestInputStream. */ - protected void annotateClass(Class cl) throws IOException { + protected void annotateClass(Class cl) throws IOException { this.writeUTF("magic"); } @@ -112,7 +112,6 @@ protected void annotateClass(Class cl) throws IOException { * Other objects are written as themselves. */ protected Object replaceObject(Object obj) - throws IOException { /* For PrintStreams, like stdout and stderr, encode */ if (obj instanceof PrintStream) { @@ -169,6 +168,7 @@ protected Object resolveObject(Object obj) { * and a small integer. */ class StdStream implements java.io.Serializable { + private static final long serialVersionUID = 1L; private int stream = 0; public StdStream(PrintStream s) { diff --git a/test/jdk/java/io/Serializable/oldTests/ArrayTest.java b/test/jdk/java/io/Serializable/oldTests/ArrayTest.java index 454eaa67002..028e1471ac6 100644 --- a/test/jdk/java/io/Serializable/oldTests/ArrayTest.java +++ b/test/jdk/java/io/Serializable/oldTests/ArrayTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,8 @@ */ public class ArrayTest implements java.io.Serializable { + private static final long serialVersionUID = 1L; + byte b[] = { 0, 1}; short s[] = { 0, 1, 2}; char c[] = { 'Z', 'Y', 'X'}; diff --git a/test/jdk/java/io/Serializable/oldTests/ArraysOfArrays.java b/test/jdk/java/io/Serializable/oldTests/ArraysOfArrays.java index 1d8f0e73afa..52aabcb4ee4 100644 --- a/test/jdk/java/io/Serializable/oldTests/ArraysOfArrays.java +++ b/test/jdk/java/io/Serializable/oldTests/ArraysOfArrays.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,40 +42,40 @@ public static void main (String argv[]) throws IOException { ostream = new FileOutputStream("piotest5.tmp"); ObjectOutputStream p = new ObjectOutputStream(ostream); - byte b[][] = {{ 0, 1}, {2,3}}; - p.writeObject((Object)b); + byte[][] b = {{ 0, 1}, {2,3}}; + p.writeObject(b); - short s[][] = {{ 0, 1, 2}, {3,4,5}}; - p.writeObject((Object)s); + short[][] s = {{ 0, 1, 2}, {3,4,5}}; + p.writeObject(s); - char c[][] = {{ 0, 1, 2, 3}, {4, 5, 6, 7}}; - p.writeObject((Object)c); + char[][] c = {{ 0, 1, 2, 3}, {4, 5, 6, 7}}; + p.writeObject(c); - int i[][] = {{ 0, 1, 2, 3, 4}, {5, 6, 7, 8, 9}}; - p.writeObject((Object)i); + int[][] i = {{ 0, 1, 2, 3, 4}, {5, 6, 7, 8, 9}}; + p.writeObject(i); - long l[][] = {{ 0, 1, 2, 3, 4, 5}, {6,7,8,9,10,11}}; + long[][] l = {{ 0, 1, 2, 3, 4, 5}, {6,7,8,9,10,11}}; p.writeObject((Object)l); - boolean z[][] = new boolean[2][2]; + boolean[][] z = new boolean[2][2]; z[0][0] = true; z[0][1] = false; z[1] = z[0]; // Use first row same as second - p.writeObject((Object)z); + p.writeObject(z); - float f[][] = {{ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}, + float[][] f = {{ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f}, { 1.1f, 2.1f, 3.1f, 4.1f, 5.1f, 6.1f}}; - p.writeObject((Object)f); + p.writeObject(f); - double d[][] = {{ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0d}, + double[][] d = {{ 1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0d}, { 1.1f, 2.1f, 3.1f, 4.1f, 5.1f, 6.1f, 7.1d}}; - p.writeObject((Object)d); + p.writeObject(d); - Integer Int[][] = {{ new Integer(3), new Integer(2)}, - { new Integer(1), new Integer(0)}}; - p.writeObject((Object)Int); + Integer Int[][] = {{ 3, 2}, + { 1, 0}}; + p.writeObject(Int); p.flush(); @@ -84,12 +84,12 @@ public static void main (String argv[]) throws IOException { istream = new FileInputStream("piotest5.tmp"); ObjectInputStream q = new ObjectInputStream(istream); - byte b_u[][] = (byte [][]) (q.readObject()); + byte[][] b_u = (byte [][]) (q.readObject()); for (int ix = 0; ix < b_u.length; ix++) { for(int iy = 0; iy < b_u[ix].length; iy++) { if (b[ix][iy] != b_u[ix][iy]) { System.err.println("\nByte array mismatch [" + - ix + "][" + iy + " expected " + b[ix][iy] + + ix + "][" + iy + "] expected " + b[ix][iy] + " actual = " + b_u[ix][iy]); throw new Error(); } @@ -97,97 +97,97 @@ public static void main (String argv[]) throws IOException { } - short s_u[][] = (short [][])(q.readObject()); - for (int ix = 0; ix < b_u.length; ix++) { - for(int iy = 0; iy < b_u[ix].length; iy++) { - if (b[ix][iy] != b_u[ix][iy]) { + short[][] s_u = (short [][])(q.readObject()); + for (int ix = 0; ix < s_u.length; ix++) { + for(int iy = 0; iy < s_u[ix].length; iy++) { + if (s[ix][iy] != s_u[ix][iy]) { System.err.println("\nshort array mismatch [" + - ix + "][" + iy + " expected " + b[ix][iy] + - " actual = " + b_u[ix][iy]); + ix + "][" + iy + "] expected " + s[ix][iy] + + " actual = " + s_u[ix][iy]); throw new Error(); } } } - char c_u[][] = (char [][])(q.readObject()); - for (int ix = 0; ix < b_u.length; ix++) { - for(int iy = 0; iy < b_u[ix].length; iy++) { - if (b[ix][iy] != b_u[ix][iy]) { + char[][] c_u = (char [][])(q.readObject()); + for (int ix = 0; ix < c_u.length; ix++) { + for(int iy = 0; iy < c_u[ix].length; iy++) { + if (c[ix][iy] != c_u[ix][iy]) { System.err.println("\nchar array mismatch [" + - ix + "][" + iy + " expected " + b[ix][iy] + - " actual = " + b_u[ix][iy]); + ix + "][" + iy + "] expected " + c[ix][iy] + + " actual = " + c_u[ix][iy]); throw new Error(); } } } - int i_u[][] = (int [][])(q.readObject()); - for (int ix = 0; ix < b_u.length; ix++) { - for(int iy = 0; iy < b_u[ix].length; iy++) { - if (b[ix][iy] != b_u[ix][iy]) { + int[][] i_u = (int [][])(q.readObject()); + for (int ix = 0; ix < i_u.length; ix++) { + for(int iy = 0; iy < i_u[ix].length; iy++) { + if (i[ix][iy] != i_u[ix][iy]) { System.err.println("\nint array mismatch [" + - ix + "][" + iy + " expected " + b[ix][iy] + - " actual = " + b_u[ix][iy]); + ix + "][" + iy + "] expected " + i[ix][iy] + + " actual = " + i_u[ix][iy]); throw new Error(); } } } - long l_u[][] = (long [][])(q.readObject()); - for (int ix = 0; ix < b_u.length; ix++) { - for(int iy = 0; iy < b_u[ix].length; iy++) { - if (b[ix][iy] != b_u[ix][iy]) { + long[][] l_u = (long [][])(q.readObject()); + for (int ix = 0; ix < l_u.length; ix++) { + for(int iy = 0; iy < l_u[ix].length; iy++) { + if (l[ix][iy] != l_u[ix][iy]) { System.err.println("\nlong array mismatch [" + - ix + "][" + iy + " expected " + b[ix][iy] + - " actual = " + b_u[ix][iy]); + ix + "][" + iy + "] expected " + l[ix][iy] + + " actual = " + l_u[ix][iy]); throw new Error(); } } } - boolean z_u[][] = (boolean [][])(q.readObject()); - for (int ix = 0; ix < b_u.length; ix++) { - for(int iy = 0; iy < b_u[ix].length; iy++) { - if (b[ix][iy] != b_u[ix][iy]) { + boolean[][] z_u = (boolean [][])(q.readObject()); + for (int ix = 0; ix < z_u.length; ix++) { + for(int iy = 0; iy < z_u[ix].length; iy++) { + if (z[ix][iy] != z_u[ix][iy]) { System.err.println("\nboolean array mismatch [" + - ix + "][" + iy + " expected " + b[ix][iy] + - " actual = " + b_u[ix][iy]); + ix + "][" + iy + "] expected " + z[ix][iy] + + " actual = " + z_u[ix][iy]); throw new Error(); } } } - float f_u[][] = (float [][])(q.readObject()); - for (int ix = 0; ix < b_u.length; ix++) { - for(int iy = 0; iy < b_u[ix].length; iy++) { - if (b[ix][iy] != b_u[ix][iy]) { + float[][] f_u = (float [][])(q.readObject()); + for (int ix = 0; ix < f_u.length; ix++) { + for(int iy = 0; iy < f_u[ix].length; iy++) { + if (f[ix][iy] != f_u[ix][iy]) { System.err.println("\nfloat array mismatch [" + - ix + "][" + iy + " expected " + b[ix][iy] + - " actual = " + b_u[ix][iy]); + ix + "][" + iy + "] expected " + f[ix][iy] + + " actual = " + f_u[ix][iy]); throw new Error(); } } } - double d_u[][] = (double [][])(q.readObject()); - for (int ix = 0; ix < b_u.length; ix++) { - for(int iy = 0; iy < b_u[ix].length; iy++) { - if (b[ix][iy] != b_u[ix][iy]) { + double[][] d_u = (double [][])(q.readObject()); + for (int ix = 0; ix < d_u.length; ix++) { + for(int iy = 0; iy < d_u[ix].length; iy++) { + if (d[ix][iy] != d_u[ix][iy]) { System.err.println("\ndouble array mismatch [" + - ix + "][" + iy + " expected " + b[ix][iy] + - " actual = " + b_u[ix][iy]); + ix + "][" + iy + "] expected " + d[ix][iy] + + " actual = " + d_u[ix][iy]); throw new Error(); } } } - Integer Int_u[][] = (Integer [][])(q.readObject()); - for (int ix = 0; ix < b_u.length; ix++) { - for(int iy = 0; iy < b_u[ix].length; iy++) { - if (b[ix][iy] != b_u[ix][iy]) { + Integer[][] Int_u = (Integer [][])(q.readObject()); + for (int ix = 0; ix < Int_u.length; ix++) { + for(int iy = 0; iy < Int_u[ix].length; iy++) { + if (!Int[ix][iy].equals(Int_u[ix][iy])) { System.err.println("\nInteger array mismatch [" + - ix + "][" + iy + " expected " + b[ix][iy] + - " actual = " + b_u[ix][iy]); + ix + "][" + iy + "] expected " + Int[ix][iy] + + " actual = " + Int_u[ix][iy]); throw new Error(); } } diff --git a/test/jdk/java/io/Serializable/oldTests/BinaryTree.java b/test/jdk/java/io/Serializable/oldTests/BinaryTree.java index 73b7799f6c5..94e9389735f 100644 --- a/test/jdk/java/io/Serializable/oldTests/BinaryTree.java +++ b/test/jdk/java/io/Serializable/oldTests/BinaryTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -75,6 +75,8 @@ public static void main (String argv[]) { } class BinaryTreeTest implements java.io.Serializable { + private static final long serialVersionUID = 1L; + public BinaryTreeTest left; public BinaryTreeTest right; public int id; diff --git a/test/jdk/java/io/Serializable/oldTests/CheckForException.java b/test/jdk/java/io/Serializable/oldTests/CheckForException.java index c9615cec110..8335352ca4d 100644 --- a/test/jdk/java/io/Serializable/oldTests/CheckForException.java +++ b/test/jdk/java/io/Serializable/oldTests/CheckForException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -105,6 +105,8 @@ public static void main (String argv[]) { } class PickleClass implements java.io.Serializable { + private static final long serialVersionUID = 1L; + int ii = 17; transient int tmp[]; @@ -129,6 +131,8 @@ private void readObjectCleanup(ObjectInputStream pr) { } class NoPickleClass extends PickleClass { + private static final long serialVersionUID = 1L; + private void writeObject(ObjectOutputStream pw) throws NotSerializableException { @@ -143,6 +147,8 @@ private void readObject(ObjectInputStream pr) } class TryPickleClass extends NoPickleClass { + private static final long serialVersionUID = 1L; + int i = 7; transient int tmp[]; diff --git a/test/jdk/java/io/Serializable/oldTests/CheckingEquality.java b/test/jdk/java/io/Serializable/oldTests/CheckingEquality.java index d77a39cb825..308bd2ddc42 100644 --- a/test/jdk/java/io/Serializable/oldTests/CheckingEquality.java +++ b/test/jdk/java/io/Serializable/oldTests/CheckingEquality.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -83,6 +83,8 @@ public static void main (String argv[]) { } class Firstpsio implements java.io.Serializable { + private static final long serialVersionUID = 1L; + String one; int two; float three[]; @@ -125,6 +127,8 @@ boolean equals(Firstpsio other) { } class Secondpsio extends Firstpsio { + private static final long serialVersionUID = 1L; + String quatre; int cinq; @@ -173,6 +177,7 @@ void init() { } class Thirdpsio extends Secondpsio { + private static final long serialVersionUID = 1L; static String ign = "ignored"; transient Object oh; @@ -184,7 +189,8 @@ class Thirdpsio extends Secondpsio { static final byte dcare = (byte) 128; private short nine = 8888; long ten; - java.util.Enumeration zero; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ + java.util.Enumeration zero; boolean equals(Thirdpsio other) { @@ -227,7 +233,7 @@ void init() { eight = (byte)8; nine = (short)9; ten = (long)100000; - java.util.Enumeration em = null; /* default */ + java.util.Enumeration em = null; /* default */ super.init(); } diff --git a/test/jdk/java/io/Serializable/oldTests/CircularList.java b/test/jdk/java/io/Serializable/oldTests/CircularList.java index a42f8acf8ac..00f81363256 100644 --- a/test/jdk/java/io/Serializable/oldTests/CircularList.java +++ b/test/jdk/java/io/Serializable/oldTests/CircularList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -68,6 +68,8 @@ public static void main (String argv[]) throws IOException { } class CircularListTest implements java.io.Serializable { + private static final long serialVersionUID = 1L; + public CircularListTest next = null; public static CircularListTest list = null; diff --git a/test/jdk/java/io/Serializable/oldTests/PrimitivesTest.java b/test/jdk/java/io/Serializable/oldTests/PrimitivesTest.java index 29c189043dd..3fe8d48ee11 100644 --- a/test/jdk/java/io/Serializable/oldTests/PrimitivesTest.java +++ b/test/jdk/java/io/Serializable/oldTests/PrimitivesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,6 +22,8 @@ */ public class PrimitivesTest implements java.io.Serializable { + private static final long serialVersionUID = 1L; + byte b = 1; char c = 'c'; float f = 3.14159f; diff --git a/test/jdk/java/io/Serializable/oldTests/ValidateClass.java b/test/jdk/java/io/Serializable/oldTests/ValidateClass.java index afb02433059..684a49fd1ac 100644 --- a/test/jdk/java/io/Serializable/oldTests/ValidateClass.java +++ b/test/jdk/java/io/Serializable/oldTests/ValidateClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,7 +64,7 @@ public static void main (String argv[]) { Validator vc_u; vc_u = (Validator)q.readObject(); - if (vc_u.validated != Integer.MIN_VALUE) { + if (Validator.validated != Integer.MIN_VALUE) { System.err.println("\nTEST FAILED: Validation callbacks did " + "not complete."); throw new Error(); @@ -80,6 +80,7 @@ public static void main (String argv[]) { } class MissingWriterClass implements java.io.Serializable { + private static final long serialVersionUID = 1L; int i = 77; private void writeObject(ObjectOutputStream pw) throws IOException { @@ -88,6 +89,7 @@ private void writeObject(ObjectOutputStream pw) throws IOException { } class MissingReaderClass implements java.io.Serializable { + private static final long serialVersionUID = 1L; int i = 77; private void readObject(ObjectInputStream pr) throws IOException { @@ -97,6 +99,8 @@ private void readObject(ObjectInputStream pr) throws IOException { class Validator implements ObjectInputValidation, java.io.Serializable { + private static final long serialVersionUID = 1L; + static int validated = Integer.MAX_VALUE; // Last value validated int priority; Validator next = null; diff --git a/test/jdk/java/io/Serializable/optionalDataEnd/OptionalDataEnd.java b/test/jdk/java/io/Serializable/optionalDataEnd/OptionalDataEnd.java index 1819552857d..f8dc145fe02 100644 --- a/test/jdk/java/io/Serializable/optionalDataEnd/OptionalDataEnd.java +++ b/test/jdk/java/io/Serializable/optionalDataEnd/OptionalDataEnd.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ import java.io.*; class Foo implements Serializable { + private static final long serialVersionUID = 1L; + int reps; Foo(int reps) { @@ -40,7 +42,7 @@ class Foo implements Serializable { private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); for (int i = 0; i < reps; i++) { - out.writeObject(new Integer(i)); + out.writeObject(i); } } diff --git a/test/jdk/java/io/Serializable/packageAccess/B.java b/test/jdk/java/io/Serializable/packageAccess/B.java index d5d7a269109..b38015a66f2 100644 --- a/test/jdk/java/io/Serializable/packageAccess/B.java +++ b/test/jdk/java/io/Serializable/packageAccess/B.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ */ public class B extends A implements java.io.Serializable { + private static final long serialVersionUID = 1L; + public B() { super(0); } diff --git a/test/jdk/java/io/Serializable/packageAccess/C.java b/test/jdk/java/io/Serializable/packageAccess/C.java index dd197e61b97..76af790b235 100644 --- a/test/jdk/java/io/Serializable/packageAccess/C.java +++ b/test/jdk/java/io/Serializable/packageAccess/C.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,8 @@ import java.io.*; public class C implements Serializable { + private static final long serialVersionUID = 1L; + Object writeReplace() throws ObjectStreamException { throw new Error("package-private writeReplace called"); } diff --git a/test/jdk/java/io/Serializable/packageAccess/D.java b/test/jdk/java/io/Serializable/packageAccess/D.java index 74e447088a1..02d4546eaeb 100644 --- a/test/jdk/java/io/Serializable/packageAccess/D.java +++ b/test/jdk/java/io/Serializable/packageAccess/D.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,4 +29,5 @@ */ public class D extends C implements java.io.Serializable { + private static final long serialVersionUID = 1L; } diff --git a/test/jdk/java/io/Serializable/packageAccess/PackageAccessTest.java b/test/jdk/java/io/Serializable/packageAccess/PackageAccessTest.java index 1d294d157cd..337f11c4739 100644 --- a/test/jdk/java/io/Serializable/packageAccess/PackageAccessTest.java +++ b/test/jdk/java/io/Serializable/packageAccess/PackageAccessTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -50,8 +50,8 @@ public class PackageAccessTest { - static Class bcl; - static Class dcl; + static Class bcl; + static Class dcl; public static void main(String[] args) throws Exception { setup(); @@ -62,7 +62,7 @@ public static void main(String[] args) throws Exception { bcl = Class.forName("B", true, ldr); dcl = Class.forName("D", true, ldr); - Object b = bcl.newInstance(); + Object b = bcl.getConstructor().newInstance(); try { swizzle(b); throw new Error("expected InvalidClassException for class B"); @@ -74,7 +74,7 @@ public static void main(String[] args) throws Exception { throw new Error("package private constructor of A invoked"); } - Object d = dcl.newInstance(); + Object d = dcl.getConstructor().newInstance(); swizzle(d); } } @@ -103,7 +103,7 @@ class TestObjectInputStream extends ObjectInputStream { super(in); } - protected Class resolveClass(ObjectStreamClass desc) + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String n = desc.getName(); diff --git a/test/jdk/java/io/Serializable/parents/EvolvedClass.java b/test/jdk/java/io/Serializable/parents/EvolvedClass.java index 90559e9c3dc..550d3e27267 100644 --- a/test/jdk/java/io/Serializable/parents/EvolvedClass.java +++ b/test/jdk/java/io/Serializable/parents/EvolvedClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -52,6 +52,8 @@ public static void main(String args[]) throws Exception{ * must not be invoked. */ class ASuperClass implements Serializable { + private static final long serialVersionUID = 1L; + String name; ASuperClass() { diff --git a/test/jdk/java/io/Serializable/parents/OriginalClass.java b/test/jdk/java/io/Serializable/parents/OriginalClass.java index 559412ec894..3e8727ffff8 100644 --- a/test/jdk/java/io/Serializable/parents/OriginalClass.java +++ b/test/jdk/java/io/Serializable/parents/OriginalClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -59,6 +59,8 @@ public static void main(String args[]) throws Exception{ class ASubClass implements Serializable { + private static final long serialVersionUID = 6341246181948372513L; + int num; ASubClass(int num) { diff --git a/test/jdk/java/io/Serializable/partialClassDesc/PartialClassDesc.java b/test/jdk/java/io/Serializable/partialClassDesc/PartialClassDesc.java index 527c3b36942..c8b8f67444e 100644 --- a/test/jdk/java/io/Serializable/partialClassDesc/PartialClassDesc.java +++ b/test/jdk/java/io/Serializable/partialClassDesc/PartialClassDesc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,7 +43,7 @@ class A implements Serializable { public class PartialClassDesc { public static void main(String[] args) throws Exception { - Class cl = Class.forName( + Class cl = Class.forName( "A", false, PartialClassDesc.class.getClassLoader()); ObjectStreamClass desc = null; try { diff --git a/test/jdk/java/io/Serializable/primitiveClasses/PrimitiveClasses.java b/test/jdk/java/io/Serializable/primitiveClasses/PrimitiveClasses.java index 14e1969148a..67530c44725 100644 --- a/test/jdk/java/io/Serializable/primitiveClasses/PrimitiveClasses.java +++ b/test/jdk/java/io/Serializable/primitiveClasses/PrimitiveClasses.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,7 +30,7 @@ public class PrimitiveClasses { public static void main(String[] args) throws Exception { - Class[] primClasses = new Class[] { + Class[] primClasses = { boolean.class, byte.class, char.class, short.class, int.class, long.class, float.class, double.class, void.class }; diff --git a/test/jdk/java/io/Serializable/proxy/Basic.java b/test/jdk/java/io/Serializable/proxy/Basic.java index 3519334710b..de218a4904a 100644 --- a/test/jdk/java/io/Serializable/proxy/Basic.java +++ b/test/jdk/java/io/Serializable/proxy/Basic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,12 +36,13 @@ interface Bar { float bar(); } // dummy invocation handler class Handler implements InvocationHandler, Serializable { + private static final long serialVersionUID = 1L; static Method fooMethod, barMethod; static { try { - fooMethod = Foo.class.getDeclaredMethod("foo", new Class[0]); - barMethod = Bar.class.getDeclaredMethod("bar", new Class[0]); + fooMethod = Foo.class.getDeclaredMethod("foo", new Class[0]); + barMethod = Bar.class.getDeclaredMethod("bar", new Class[0]); } catch (NoSuchMethodException ex) { throw new Error(); } @@ -59,9 +60,9 @@ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { if (method.equals(fooMethod)) { - return new Integer(foo); + return foo; } else if (method.equals(barMethod)) { - return new Float(bar); + return bar; } else { throw new UnsupportedOperationException(); } @@ -73,7 +74,7 @@ class ProxyBlindInputStream extends ObjectInputStream { ProxyBlindInputStream(InputStream in) throws IOException { super(in); } - protected Class resolveProxyClass(String[] interfaces) + protected Class resolveProxyClass(String[] interfaces) throws IOException, ClassNotFoundException { throw new ClassNotFoundException(); @@ -83,7 +84,7 @@ protected Class resolveProxyClass(String[] interfaces) public class Basic { public static void main(String[] args) throws Exception { ClassLoader loader = Basic.class.getClassLoader(); - Class[] interfaces = new Class[] { Foo.class, Bar.class }; + Class[] interfaces = { Foo.class, Bar.class }; Random rand = new Random(); int foo = rand.nextInt(); float bar = rand.nextFloat(); diff --git a/test/jdk/java/io/Serializable/proxy/replace/Test.java b/test/jdk/java/io/Serializable/proxy/replace/Test.java index b5aefea5062..0c8838b5415 100644 --- a/test/jdk/java/io/Serializable/proxy/replace/Test.java +++ b/test/jdk/java/io/Serializable/proxy/replace/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.lang.reflect.*; public class Test implements InvocationHandler, Serializable { + private static final long serialVersionUID = 1L; static ClassLoader loader = Test.class.getClassLoader(); @@ -39,10 +40,10 @@ public Object invoke(Object proxy, Method method, Object[] args) String methName = method.getName(); if (methName.equals("writeReplace")) { return Proxy.newProxyInstance( - loader, new Class[] { ReadResolve.class }, this); + loader, new Class[] { ReadResolve.class }, this); } else if (methName.equals("readResolve")) { return Proxy.newProxyInstance( - loader, new Class[] { Resolved.class }, this); + loader, new Class[] { Resolved.class }, this); } else if (method.getDeclaringClass() == Object.class) { return method.invoke(this, args); } else { @@ -54,7 +55,7 @@ public static void main(String[] args) throws Exception { ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(bout); oout.writeObject(Proxy.newProxyInstance( - loader, new Class[] { WriteReplace.class }, new Test())); + loader, new Class[] { WriteReplace.class }, new Test())); oout.close(); ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream(bout.toByteArray())); diff --git a/test/jdk/java/io/Serializable/proxy/skipMissing/Handler.java b/test/jdk/java/io/Serializable/proxy/skipMissing/Handler.java index 2039955d740..7a853cb17b7 100644 --- a/test/jdk/java/io/Serializable/proxy/skipMissing/Handler.java +++ b/test/jdk/java/io/Serializable/proxy/skipMissing/Handler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ import java.lang.reflect.*; class Handler implements InvocationHandler, Serializable { + private static final long serialVersionUID = 1L; + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { diff --git a/test/jdk/java/io/Serializable/proxy/skipMissing/Write.java b/test/jdk/java/io/Serializable/proxy/skipMissing/Write.java index fac6556c11e..59b22a16bcf 100644 --- a/test/jdk/java/io/Serializable/proxy/skipMissing/Write.java +++ b/test/jdk/java/io/Serializable/proxy/skipMissing/Write.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,7 @@ interface I {} // interface present only on writing side class A implements Serializable { private static final long serialVersionUID = 0L; String a = "a"; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ Object proxy; String z = "z"; @@ -65,7 +66,7 @@ public class Write { public static void main(String[] args) throws Exception { Object proxy = Proxy.newProxyInstance( Write.class.getClassLoader(), - new Class[] { I.class }, new Handler()); + new Class[] { I.class }, new Handler()); ObjectOutputStream oout = new ObjectOutputStream( new FileOutputStream("tmp.ser")); oout.writeObject(new A(proxy)); diff --git a/test/jdk/java/io/Serializable/readObjectNoData/Read.java b/test/jdk/java/io/Serializable/readObjectNoData/Read.java index f2550030a50..e1e13861026 100644 --- a/test/jdk/java/io/Serializable/readObjectNoData/Read.java +++ b/test/jdk/java/io/Serializable/readObjectNoData/Read.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -48,6 +48,7 @@ private void readObjectNoData() throws ObjectStreamException { class B extends A implements Serializable { private static final long serialVersionUID = 0L; boolean bCalled = false; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private void readObjectNoData(int wrong) throws ObjectStreamException { bCalled = true; } @@ -82,6 +83,7 @@ private void readObjectNoData() throws ObjectStreamException { class E extends D { private static final long serialVersionUID = 0L; boolean eCalled = false; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ void readObjectNoData() throws ObjectStreamException { eCalled = true; } diff --git a/test/jdk/java/io/Serializable/recursiveClassDescLookup/Test.java b/test/jdk/java/io/Serializable/recursiveClassDescLookup/Test.java index 03ca88fd6ea..b127f318095 100644 --- a/test/jdk/java/io/Serializable/recursiveClassDescLookup/Test.java +++ b/test/jdk/java/io/Serializable/recursiveClassDescLookup/Test.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ class Foo implements Serializable { public class Test { public static void main(String[] args) throws Exception { - Class fooCl = Class.forName("Foo", false, Test.class.getClassLoader()); + Class fooCl = Class.forName("Foo", false, Test.class.getClassLoader()); ObjectStreamClass.lookup(fooCl); System.out.println("done."); } diff --git a/test/jdk/java/io/Serializable/replaceStringArray/ReplaceStringArray.java b/test/jdk/java/io/Serializable/replaceStringArray/ReplaceStringArray.java index 1dc432bcc8f..8c4a2f36721 100644 --- a/test/jdk/java/io/Serializable/replaceStringArray/ReplaceStringArray.java +++ b/test/jdk/java/io/Serializable/replaceStringArray/ReplaceStringArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ import java.lang.reflect.Array; class A implements Serializable { + private static final long serialVersionUID = 1L; + String stringA; String stringB; String stringC; @@ -74,7 +76,7 @@ protected Object replaceObject(Object obj) throws IOException { Object[] array = (Object[]) obj; /* Double the array. * Initialize new array elements with original array. */ - Class arrayComponentType = array.getClass().getComponentType(); + Class arrayComponentType = array.getClass().getComponentType(); Object[] newarray = (Object[])Array.newInstance(arrayComponentType, array.length * 2); @@ -108,7 +110,7 @@ protected Object resolveObject(Object obj) throws IOException { /* Double the array. * Initialize new array elements with original array. */ - Class arrayComponentType = array.getClass().getComponentType(); + Class arrayComponentType = array.getClass().getComponentType(); Object[] newarray = (Object[])Array.newInstance(arrayComponentType, array.length * 2); diff --git a/test/jdk/java/io/Serializable/resolveClass/MethodTest.java b/test/jdk/java/io/Serializable/resolveClass/MethodTest.java index 5b28a9877c0..6b72af94673 100644 --- a/test/jdk/java/io/Serializable/resolveClass/MethodTest.java +++ b/test/jdk/java/io/Serializable/resolveClass/MethodTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,9 +31,11 @@ import java.lang.reflect.*; public class MethodTest implements Serializable { + private static final long serialVersionUID = 1L; + public static void main(String[] args) throws Exception { Method readObject = ObjectInputStream.class.getDeclaredMethod( - "readObject", new Class[0]); + "readObject", new Class[0]); ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(bout); oout.writeObject(new MethodTest()); diff --git a/test/jdk/java/io/Serializable/resolveClass/consTest/ConsTest.java b/test/jdk/java/io/Serializable/resolveClass/consTest/ConsTest.java index 0e0f9a8aa34..8b7481d58d3 100644 --- a/test/jdk/java/io/Serializable/resolveClass/consTest/ConsTest.java +++ b/test/jdk/java/io/Serializable/resolveClass/consTest/ConsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,9 +42,10 @@ import jdk.test.lib.util.JarUtils; public class ConsTest implements Serializable { + private static final long serialVersionUID = 1L; + public static void main(String[] args) throws Exception { - Constructor cons = Boot.class.getConstructor( - new Class[] { ObjectInputStream.class }); + Constructor cons = Boot.class.getConstructor(ObjectInputStream.class); ByteArrayOutputStream bout = new ByteArrayOutputStream(); ObjectOutputStream oout = new ObjectOutputStream(bout); oout.writeObject(new ConsTest()); @@ -53,7 +54,7 @@ public static void main(String[] args) throws Exception { for (int i = 0; i < 100; i++) { ObjectInputStream oin = new ObjectInputStream( new ByteArrayInputStream(bout.toByteArray())); - cons.newInstance(new Object[]{ oin }); + cons.newInstance(oin); } } } diff --git a/test/jdk/java/io/Serializable/resolveClass/deserializeButton/DeserializeButtonTest.java b/test/jdk/java/io/Serializable/resolveClass/deserializeButton/DeserializeButtonTest.java index b538bdf4536..618b7e084cb 100644 --- a/test/jdk/java/io/Serializable/resolveClass/deserializeButton/DeserializeButtonTest.java +++ b/test/jdk/java/io/Serializable/resolveClass/deserializeButton/DeserializeButtonTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,8 @@ public static void main(String[] args) throws Exception { try (URLClassLoader ldr = new URLClassLoader(new URL[]{ new URL("file:cb.jar") })) { - Runnable r = (Runnable) Class.forName("Foo", true, ldr).newInstance(); + Runnable r = (Runnable) Class.forName("Foo", true, ldr) + .getConstructor().newInstance(); r.run(); } } diff --git a/test/jdk/java/io/Serializable/resolveClass/deserializeButton/Foo.java b/test/jdk/java/io/Serializable/resolveClass/deserializeButton/Foo.java index edfb2ee00f3..9ce9453d91d 100644 --- a/test/jdk/java/io/Serializable/resolveClass/deserializeButton/Foo.java +++ b/test/jdk/java/io/Serializable/resolveClass/deserializeButton/Foo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,7 +34,9 @@ public class Foo implements Runnable { - static class TestElement extends Object implements Serializable {} + static class TestElement extends Object implements Serializable { + private static final long serialVersionUID = 1L; + } public void run() { try { diff --git a/test/jdk/java/io/Serializable/resolveClassException/ResolveClassException.java b/test/jdk/java/io/Serializable/resolveClassException/ResolveClassException.java index 2ac49086902..5fd6f005231 100644 --- a/test/jdk/java/io/Serializable/resolveClassException/ResolveClassException.java +++ b/test/jdk/java/io/Serializable/resolveClassException/ResolveClassException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,8 +37,8 @@ class BrokenObjectInputStream extends ObjectInputStream { super(in); } - protected Class resolveClass(ObjectStreamClass desc) - throws IOException, ClassNotFoundException + protected Class resolveClass(ObjectStreamClass desc) + throws ClassNotFoundException { throw new ClassNotFoundException(message); } @@ -53,7 +53,7 @@ public static void main(String[] args) throws Exception { Object obj; // write and read an object - obj = new Integer(5); + obj = 5; bout = new ByteArrayOutputStream(); oout = new ObjectOutputStream(bout); oout.writeObject(obj); @@ -67,7 +67,7 @@ public static void main(String[] args) throws Exception { } // write and read an array of objects - obj = new Integer[] { new Integer(5) }; + obj = new Integer[] { 5 }; bout = new ByteArrayOutputStream(); oout = new ObjectOutputStream(bout); oout.writeObject(obj); diff --git a/test/jdk/java/io/Serializable/resolveProxyClass/NonPublicInterface.java b/test/jdk/java/io/Serializable/resolveProxyClass/NonPublicInterface.java index 802c6439a0e..c647b56da71 100644 --- a/test/jdk/java/io/Serializable/resolveProxyClass/NonPublicInterface.java +++ b/test/jdk/java/io/Serializable/resolveProxyClass/NonPublicInterface.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,8 @@ public class NonPublicInterface { static class Handler implements InvocationHandler, Serializable { + private static final long serialVersionUID = 1L; + public Object invoke(Object obj, Method meth, Object[] args) { return null; } diff --git a/test/jdk/java/io/Serializable/sanityCheck/SanityCheck.java b/test/jdk/java/io/Serializable/sanityCheck/SanityCheck.java index e2659868fe8..29b47b0d9c6 100644 --- a/test/jdk/java/io/Serializable/sanityCheck/SanityCheck.java +++ b/test/jdk/java/io/Serializable/sanityCheck/SanityCheck.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,6 +31,7 @@ import java.util.*; class Item implements Serializable { + private static final long serialVersionUID = 1L; static final int ARRAYLEN = 1000; static final int STRLEN = 1000; @@ -55,6 +56,7 @@ class Item implements Serializable { double[] dary; String str; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ Object[] oary; Item() { @@ -86,7 +88,7 @@ class Item implements Serializable { fary[i] = rand.nextFloat(); jary[i] = rand.nextLong(); dary[i] = rand.nextDouble(); - oary[i] = new Integer(rand.nextInt()); + oary[i] = rand.nextInt(); } char[] strChars = new char[STRLEN]; @@ -126,6 +128,11 @@ public boolean equals(Object obj) { return true; } + + @Override + public int hashCode() { + return Objects.hash(i, j); + } } public class SanityCheck { diff --git a/test/jdk/java/io/Serializable/serialFilter/SerialFilterTest.java b/test/jdk/java/io/Serializable/serialFilter/SerialFilterTest.java index 279dfe7a44f..a4c78919878 100644 --- a/test/jdk/java/io/Serializable/serialFilter/SerialFilterTest.java +++ b/test/jdk/java/io/Serializable/serialFilter/SerialFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -775,6 +775,7 @@ private static void noop() {} static class ReadResolveToArray implements Serializable, ObjectInputFilter { private static final long serialVersionUID = 123456789L; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ private final Object array; private final int length; diff --git a/test/jdk/java/io/Serializable/serialver/classpath/ClasspathTest.java b/test/jdk/java/io/Serializable/serialver/classpath/ClasspathTest.java index 92986eb5aea..d2e8beb1f62 100644 --- a/test/jdk/java/io/Serializable/serialver/classpath/ClasspathTest.java +++ b/test/jdk/java/io/Serializable/serialver/classpath/ClasspathTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,7 @@ import jdk.test.lib.process.ProcessTools; public class ClasspathTest implements java.io.Serializable { + private static final long serialVersionUID = 1L; int a; int b; diff --git a/test/jdk/java/io/Serializable/serialver/nested/NestedTest.java b/test/jdk/java/io/Serializable/serialver/nested/NestedTest.java index 9b8963b355e..b94b07ad801 100644 --- a/test/jdk/java/io/Serializable/serialver/nested/NestedTest.java +++ b/test/jdk/java/io/Serializable/serialver/nested/NestedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -45,7 +45,11 @@ import jdk.test.lib.process.ProcessTools; public class NestedTest implements Serializable { + private static final long serialVersionUID = 1L; + public static class Test1 implements Serializable { + private static final long serialVersionUID = 1L; + public static class Test2 implements Serializable{ private static final long serialVersionUID = 100L; } diff --git a/test/jdk/java/io/Serializable/skipToEndOfBlockData/SkipToEndOfBlockData.java b/test/jdk/java/io/Serializable/skipToEndOfBlockData/SkipToEndOfBlockData.java index c2fc1bf3f2e..9083f577627 100644 --- a/test/jdk/java/io/Serializable/skipToEndOfBlockData/SkipToEndOfBlockData.java +++ b/test/jdk/java/io/Serializable/skipToEndOfBlockData/SkipToEndOfBlockData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,8 @@ import java.io.*; class MismatchedRead implements Serializable { + private static final long serialVersionUID = 1L; + int i; float f; @@ -59,9 +61,15 @@ public boolean equals(Object obj) { MismatchedRead other = (MismatchedRead) obj; return (i == other.i && f == other.f); } + + public int hashCode() { + return i; + } } class MismatchedReadExternal implements Externalizable { + private static final long serialVersionUID = 1L; + int i; float f; @@ -91,9 +99,15 @@ public boolean equals(Object obj) { MismatchedReadExternal other = (MismatchedReadExternal) obj; return (i == other.i && f == other.f); } + + public int hashCode() { + return i; + } } class InnocentBystander implements Serializable { + private static final long serialVersionUID = 1L; + String s; InnocentBystander(String s) { @@ -108,6 +122,10 @@ public boolean equals(Object obj) { return s.equals(other.s); return (s == other.s); } + + public int hashCode() { + return s.hashCode(); + } } public class SkipToEndOfBlockData { diff --git a/test/jdk/java/io/Serializable/skipWriteObject/Write.java b/test/jdk/java/io/Serializable/skipWriteObject/Write.java index df862f152f7..116c3c48c0d 100644 --- a/test/jdk/java/io/Serializable/skipWriteObject/Write.java +++ b/test/jdk/java/io/Serializable/skipWriteObject/Write.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -44,6 +44,8 @@ class Foo implements Serializable { } class Bar implements Serializable { + private static final long serialVersionUID = 1L; + int a, b; private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); diff --git a/test/jdk/java/io/Serializable/skippedObjCNFException/Read.java b/test/jdk/java/io/Serializable/skippedObjCNFException/Read.java index 1be47aac77c..6786bf4610a 100644 --- a/test/jdk/java/io/Serializable/skippedObjCNFException/Read.java +++ b/test/jdk/java/io/Serializable/skippedObjCNFException/Read.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ class A implements Serializable { class B implements Serializable { private static final long serialVersionUID = 0L; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ Object c; } diff --git a/test/jdk/java/io/Serializable/skippedObjCNFException/Write.java b/test/jdk/java/io/Serializable/skippedObjCNFException/Write.java index 6b5a9ec2153..b34aa7e64a8 100644 --- a/test/jdk/java/io/Serializable/skippedObjCNFException/Write.java +++ b/test/jdk/java/io/Serializable/skippedObjCNFException/Write.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,11 +43,13 @@ class A implements Serializable { // all three following fields not present on reading side B b = new B(); C c = new C(); + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ Object ca = new Object[] { new C() }; } class B implements Serializable { private static final long serialVersionUID = 0L; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ Object c = new C(); } diff --git a/test/jdk/java/io/Serializable/stopCustomDeserialization/Read.java b/test/jdk/java/io/Serializable/stopCustomDeserialization/Read.java index afdffe6df7c..c9f2477dff7 100644 --- a/test/jdk/java/io/Serializable/stopCustomDeserialization/Read.java +++ b/test/jdk/java/io/Serializable/stopCustomDeserialization/Read.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ class A implements Serializable { private static final long serialVersionUID = 0L; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ Object x; } diff --git a/test/jdk/java/io/Serializable/stopCustomDeserialization/Write.java b/test/jdk/java/io/Serializable/stopCustomDeserialization/Write.java index b2f3ad3f87c..fd73f5b13e2 100644 --- a/test/jdk/java/io/Serializable/stopCustomDeserialization/Write.java +++ b/test/jdk/java/io/Serializable/stopCustomDeserialization/Write.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ class A implements Serializable { private static final long serialVersionUID = 0L; + @SuppressWarnings("serial") /* Incorrect declarations are being tested */ Object x = new X(); } diff --git a/test/jdk/java/io/Serializable/subclass/AbstractObjectInputStream.java b/test/jdk/java/io/Serializable/subclass/AbstractObjectInputStream.java index 29150f3bcfb..ea2245f265d 100644 --- a/test/jdk/java/io/Serializable/subclass/AbstractObjectInputStream.java +++ b/test/jdk/java/io/Serializable/subclass/AbstractObjectInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -253,7 +253,7 @@ public abstract void defaultReadObject() * @exception InstantiationException TBD. */ protected final native Object - allocateNewObject(Class ofClass, Class ctorClass) + allocateNewObject(Class ofClass, Class ctorClass) throws InstantiationException, IllegalAccessException; /** @@ -271,7 +271,7 @@ public abstract void defaultReadObject() * @exception InstantiationException TBD. */ protected final native Object - allocateNewArray(Class componentClass, int length) + allocateNewArray(Class componentClass, int length) throws InstantiationException, IllegalAccessException; /** @@ -317,5 +317,6 @@ public abstract int read(byte[] data, int offset, int length) public abstract int skipBytes(int len) throws IOException; /* @deprecated */ + @SuppressWarnings("deprecation") public abstract String readLine() throws IOException; }; diff --git a/test/jdk/java/io/Serializable/subclass/SubclassTest.java b/test/jdk/java/io/Serializable/subclass/SubclassTest.java index 916e1d4295c..1b604f16b28 100644 --- a/test/jdk/java/io/Serializable/subclass/SubclassTest.java +++ b/test/jdk/java/io/Serializable/subclass/SubclassTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -57,6 +57,8 @@ * Test if customized readObject and writeObject are called. */ class B implements Serializable { + private static final long serialVersionUID = 1L; + public int publicIntField; public static int numWriteObjectCalled = 0; B(int v) { @@ -80,9 +82,11 @@ private void readObject(ObjectInputStream is) */ class C implements Serializable { + private static final long serialVersionUID = 1L; + public int xx1; public int xx2; - static final ObjectStreamField[] serialPersistentFields = { + private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("x1", Integer.TYPE), new ObjectStreamField("x2", Integer.TYPE), new ObjectStreamField("x3", Integer.TYPE), @@ -106,6 +110,8 @@ private void writeObject(ObjectOutputStream os) throws IOException { class A implements Serializable { + private static final long serialVersionUID = 1L; + public int publicIntField; public long publicLongField; public B publicBField; diff --git a/test/jdk/java/io/Serializable/subclass/XObjectInputStream.java b/test/jdk/java/io/Serializable/subclass/XObjectInputStream.java index a333dea560b..75004b17531 100644 --- a/test/jdk/java/io/Serializable/subclass/XObjectInputStream.java +++ b/test/jdk/java/io/Serializable/subclass/XObjectInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -47,7 +47,7 @@ protected final Object readObjectOverride() Object readResult = null; Object prevObject = currentObject; - Class prevDesc = currentClassDescriptor; + Class prevDesc = currentClassDescriptor; boolean NotImplemented = true; if (NotImplemented) @@ -243,7 +243,7 @@ public void read(ObjectInputStream in) } private Object currentObject; - private Class currentClassDescriptor; + private Class currentClassDescriptor; @@ -256,15 +256,15 @@ public void read(ObjectInputStream in) * Set the accessible flag on it here. ObjectOutputStream * will call it as necessary. */ - public static Method getReadObjectMethod(final Class cl) { + public static Method getReadObjectMethod(final Class cl) { - Method readObjectMethod = (Method) + Method readObjectMethod = java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public Object run() { + (new java.security.PrivilegedAction() { + public Method run() { Method m = null; try { - Class[] args = {ObjectInputStream.class}; + Class[] args = {ObjectInputStream.class}; m = cl.getDeclaredMethod("readObject", args); int mods = m.getModifiers(); // Method must be private and non-static @@ -292,8 +292,8 @@ private static void invokeMethod(final Object obj, final Method m, { try { java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public Object run() throws InvocationTargetException, + (new java.security.PrivilegedExceptionAction() { + public Void run() throws InvocationTargetException, java.lang.IllegalAccessException { m.invoke(obj, argList); return null; diff --git a/test/jdk/java/io/Serializable/subclass/XObjectOutputStream.java b/test/jdk/java/io/Serializable/subclass/XObjectOutputStream.java index 583f1d04bdc..7bed2cfb36d 100644 --- a/test/jdk/java/io/Serializable/subclass/XObjectOutputStream.java +++ b/test/jdk/java/io/Serializable/subclass/XObjectOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -116,7 +116,7 @@ public void defaultWriteObject() throws IOException { int mods = fields[i].getModifiers(); if (Modifier.isStatic(mods) || Modifier.isTransient(mods)) continue; - Class FieldType = fields[i].getType(); + Class FieldType = fields[i].getType(); if (FieldType.isPrimitive()) { System.out.println("Field " + fields[i].getName() + " has primitive type " + FieldType.toString()); @@ -127,7 +127,7 @@ public void defaultWriteObject() throws IOException { writeObject(fields[i].get(obj)); if (FieldType.isArray()) { Object[] array = ((Object[]) fields[i].get(obj)); - Class componentType = FieldType.getComponentType(); + Class componentType = FieldType.getComponentType(); if (componentType.isPrimitive()) System.out.println("Output " + array.length + " primitive elements of" + componentType.toString()); @@ -227,6 +227,7 @@ public void put(String name, Object value) { /** * Write the data and fields to the specified ObjectOutput stream. */ + @SuppressWarnings("deprecation") public void write(ObjectOutput out) throws IOException { for (int i = 0; i < next; i++) System.out.println(fieldName[i] + "=" + intValue[i]); @@ -300,15 +301,15 @@ public void drain() throws IOException {} * Set the accessible flag on it here. * Subclass of AbstractObjectOutputStream will call it as necessary. */ - public static Method getWriteObjectMethod(final Class cl) { + public static Method getWriteObjectMethod(final Class cl) { - Method writeObjectMethod = (Method) + Method writeObjectMethod = java.security.AccessController.doPrivileged - (new java.security.PrivilegedAction() { - public Object run() { + (new java.security.PrivilegedAction() { + public Method run() { Method m = null; try { - Class[] args = {ObjectOutputStream.class}; + Class[] args = {ObjectOutputStream.class}; m = cl.getDeclaredMethod("writeObject", args); int mods = m.getModifiers(); // Method must be private and non-static @@ -336,8 +337,8 @@ private static void invokeMethod(final Object obj, final Method m, { try { java.security.AccessController.doPrivileged - (new java.security.PrivilegedExceptionAction() { - public Object run() throws InvocationTargetException, + (new java.security.PrivilegedExceptionAction() { + public Void run() throws InvocationTargetException, java.lang.IllegalAccessException { m.invoke(obj, argList); return null; diff --git a/test/jdk/java/io/Serializable/superclassDataLoss/A.java b/test/jdk/java/io/Serializable/superclassDataLoss/A.java index e930d2cc8c4..322d941bc57 100644 --- a/test/jdk/java/io/Serializable/superclassDataLoss/A.java +++ b/test/jdk/java/io/Serializable/superclassDataLoss/A.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ */ public class A implements java.io.Serializable { + private static final long serialVersionUID = 1L; + protected final int i; protected A(int i) { this.i = i; } } diff --git a/test/jdk/java/io/Serializable/superclassDataLoss/B.java b/test/jdk/java/io/Serializable/superclassDataLoss/B.java index ff728ae40df..f7c9d8eb633 100644 --- a/test/jdk/java/io/Serializable/superclassDataLoss/B.java +++ b/test/jdk/java/io/Serializable/superclassDataLoss/B.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,8 @@ */ public class B extends A implements Runnable { + private static final long serialVersionUID = 1L; + public B() { super(0xDEADBEEF); } // verify superclass data still present diff --git a/test/jdk/java/io/Serializable/superclassDataLoss/SuperclassDataLossTest.java b/test/jdk/java/io/Serializable/superclassDataLoss/SuperclassDataLossTest.java index 3baaa9c0640..3021a746292 100644 --- a/test/jdk/java/io/Serializable/superclassDataLoss/SuperclassDataLossTest.java +++ b/test/jdk/java/io/Serializable/superclassDataLoss/SuperclassDataLossTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ class MixedSuperclassStream extends ObjectInputStream { this.ldr12A = ldr12A; } - protected Class resolveClass(ObjectStreamClass desc) + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { // resolve A's classdesc to class != B's superclass @@ -91,7 +91,8 @@ public static void main(String[] args) throws Exception { URLClassLoader ldr2 = new URLClassLoader(new URL[] { new URL("file:cb2.jar") })) { setup(); - Runnable a = (Runnable) Class.forName("B", true, ldr1).newInstance(); + Runnable a = (Runnable) Class.forName("B", true, ldr1) + .getConstructor().newInstance(); a.run(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); diff --git a/test/jdk/java/io/Serializable/survivePrematureClose/SurvivePrematureClose.java b/test/jdk/java/io/Serializable/survivePrematureClose/SurvivePrematureClose.java index 093d6cc5d87..17b668e79cf 100644 --- a/test/jdk/java/io/Serializable/survivePrematureClose/SurvivePrematureClose.java +++ b/test/jdk/java/io/Serializable/survivePrematureClose/SurvivePrematureClose.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -32,6 +32,7 @@ import java.io.*; class A implements Externalizable { + private static final long serialVersionUID = 1L; public A() {} @@ -49,6 +50,7 @@ public void readExternal(ObjectInput in) } class B implements Serializable { + private static final long serialVersionUID = 1L; private void writeObject(ObjectOutputStream out) throws IOException { out.defaultWriteObject(); diff --git a/test/jdk/java/io/Serializable/typeSafeEnum/TypeSafeEnum.java b/test/jdk/java/io/Serializable/typeSafeEnum/TypeSafeEnum.java index 512fdd2da1f..d5d1fe57b25 100644 --- a/test/jdk/java/io/Serializable/typeSafeEnum/TypeSafeEnum.java +++ b/test/jdk/java/io/Serializable/typeSafeEnum/TypeSafeEnum.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,8 @@ import java.io.*; public class TypeSafeEnum implements Serializable, ObjectInputValidation { + private static final long serialVersionUID = 1L; + private static int numWriteObject = 0; private static int numReadObject = 0; @@ -47,7 +49,7 @@ private TypeSafeEnum(String value) { static boolean verbose = false; - private Object writeReplace() throws IOException { + private Object writeReplace() { numWriteReplace++; if (verbose) { System.out.println("TypeSafeEnum.writeReplace() " + @@ -56,7 +58,7 @@ private Object writeReplace() throws IOException { return this; } - private Object readResolve() throws IOException { + private Object readResolve() { numReadResolve++; if (verbose) { System.out.println("readResolve called on " + this.toString()); diff --git a/test/jdk/java/io/Serializable/typeStringBackRef/TypeStringBackRef.java b/test/jdk/java/io/Serializable/typeStringBackRef/TypeStringBackRef.java index 8cb94b2593b..cf4660b5708 100644 --- a/test/jdk/java/io/Serializable/typeStringBackRef/TypeStringBackRef.java +++ b/test/jdk/java/io/Serializable/typeStringBackRef/TypeStringBackRef.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.io.*; public class TypeStringBackRef implements Serializable { + private static final long serialVersionUID = 1L; String a, b, c, d, e, f, g; diff --git a/test/jdk/java/io/Serializable/underlyingOutputStreamException/UnderlyingOutputStreamException.java b/test/jdk/java/io/Serializable/underlyingOutputStreamException/UnderlyingOutputStreamException.java index 7a4742e4e38..220b35d07cd 100644 --- a/test/jdk/java/io/Serializable/underlyingOutputStreamException/UnderlyingOutputStreamException.java +++ b/test/jdk/java/io/Serializable/underlyingOutputStreamException/UnderlyingOutputStreamException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,7 @@ import java.io.*; class OriginalIOException extends IOException { + private static final long serialVersionUID = 1L; } class BrokenOutputStream extends OutputStream { diff --git a/test/jdk/java/io/Serializable/unnamedPackageSwitch/UnnamedPackageSwitchTest.java b/test/jdk/java/io/Serializable/unnamedPackageSwitch/UnnamedPackageSwitchTest.java index 9f2b9c88ba9..4b3cd9d7d48 100644 --- a/test/jdk/java/io/Serializable/unnamedPackageSwitch/UnnamedPackageSwitchTest.java +++ b/test/jdk/java/io/Serializable/unnamedPackageSwitch/UnnamedPackageSwitchTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -46,7 +46,7 @@ class A implements Serializable { class TestObjectInputStream extends ObjectInputStream { TestObjectInputStream(InputStream in) throws IOException { super(in); } - protected Class resolveClass(ObjectStreamClass desc) + protected Class resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException { String name = desc.getName(); diff --git a/test/jdk/java/io/Serializable/unresolvableObjectStreamClass/UnresolvableObjectStreamClass.java b/test/jdk/java/io/Serializable/unresolvableObjectStreamClass/UnresolvableObjectStreamClass.java index 4010b1a76fa..dd48299b11b 100644 --- a/test/jdk/java/io/Serializable/unresolvableObjectStreamClass/UnresolvableObjectStreamClass.java +++ b/test/jdk/java/io/Serializable/unresolvableObjectStreamClass/UnresolvableObjectStreamClass.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -65,4 +65,5 @@ public static void main(String[] args) throws Throwable { } class MySerializable implements Serializable { + private static final long serialVersionUID = 1L; } diff --git a/test/jdk/java/io/Serializable/unresolvedClassDesc/Foo.java b/test/jdk/java/io/Serializable/unresolvedClassDesc/Foo.java index e8bf283b43c..d3d4fa9eab0 100644 --- a/test/jdk/java/io/Serializable/unresolvedClassDesc/Foo.java +++ b/test/jdk/java/io/Serializable/unresolvedClassDesc/Foo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,4 +29,5 @@ */ public class Foo implements java.io.Serializable { + private static final long serialVersionUID = 1L; } diff --git a/test/jdk/java/io/Serializable/unshared/Write.java b/test/jdk/java/io/Serializable/unshared/Write.java index 357235d91cc..ded75d2c22b 100644 --- a/test/jdk/java/io/Serializable/unshared/Write.java +++ b/test/jdk/java/io/Serializable/unshared/Write.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,8 @@ import java.io.*; class Foo implements Serializable { + private static final long serialVersionUID = 1L; + private static final ObjectStreamField[] serialPersistentFields = new ObjectStreamField[] { new ObjectStreamField("shared1", String.class), @@ -54,6 +56,7 @@ class Foo implements Serializable { class Bar implements Serializable { private static final long serialVersionUID = 0L; + @SuppressWarnings("serial") /* Incorrect use is being tested */ Object obj; Bar(Object obj) { diff --git a/test/jdk/java/io/Serializable/userRWObjError/UserRWObjError.java b/test/jdk/java/io/Serializable/userRWObjError/UserRWObjError.java index 2d07a7d9aee..39fb200bacf 100644 --- a/test/jdk/java/io/Serializable/userRWObjError/UserRWObjError.java +++ b/test/jdk/java/io/Serializable/userRWObjError/UserRWObjError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -39,6 +39,7 @@ */ public class UserRWObjError implements java.io.Serializable { + private static final long serialVersionUID = 1L; public static void main(String[] args) throws Exception { try { diff --git a/test/jdk/java/io/Serializable/validate/Validate.java b/test/jdk/java/io/Serializable/validate/Validate.java index 50a5830fdde..c703c1d6b1f 100644 --- a/test/jdk/java/io/Serializable/validate/Validate.java +++ b/test/jdk/java/io/Serializable/validate/Validate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -73,6 +73,8 @@ public static void main(String[] args) throws Exception { } class Class1 implements Serializable, ObjectInputValidation { + private static final long serialVersionUID = 1L; + int a, b; transient int validates; diff --git a/test/jdk/java/io/Serializable/verifyDynamicObjHandleTable/VerifyDynamicObjHandleTable.java b/test/jdk/java/io/Serializable/verifyDynamicObjHandleTable/VerifyDynamicObjHandleTable.java index 80933edd12d..0081708de06 100644 --- a/test/jdk/java/io/Serializable/verifyDynamicObjHandleTable/VerifyDynamicObjHandleTable.java +++ b/test/jdk/java/io/Serializable/verifyDynamicObjHandleTable/VerifyDynamicObjHandleTable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,9 @@ import java.util.Iterator; class A implements Serializable { - static HashSet writeObjectExtent = new HashSet(); + private static final long serialVersionUID = 1L; + + static HashSet writeObjectExtent = new HashSet<>(); private void writeObject(ObjectOutputStream out) throws IOException { if (writeObjectExtent.contains(this)) { @@ -63,7 +65,7 @@ public static void main(String args[]) // allow writeObject to be called on any objects that // have already been serialized. These objects should be // written out by reference. - Iterator iter = A.writeObjectExtent.iterator(); + Iterator iter = A.writeObjectExtent.iterator(); while (iter.hasNext()) { out.writeObject(iter.next()); } diff --git a/test/jdk/java/io/Serializable/writeObjectMemory/WriteObjectMemory.java b/test/jdk/java/io/Serializable/writeObjectMemory/WriteObjectMemory.java index fb602203c43..4a1312beb02 100644 --- a/test/jdk/java/io/Serializable/writeObjectMemory/WriteObjectMemory.java +++ b/test/jdk/java/io/Serializable/writeObjectMemory/WriteObjectMemory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -33,7 +33,9 @@ import java.util.Iterator; class A implements Serializable { - static HashSet writeObjectExtent = new HashSet(); + private static final long serialVersionUID = 1L; + + static HashSetwriteObjectExtent = new HashSet<>(); private void writeObject(ObjectOutputStream out) throws IOException { if (writeObjectExtent.contains(this)) { @@ -53,7 +55,7 @@ private void writeObject(ObjectOutputStream out) throws IOException { public class WriteObjectMemory { public static void main(String args[]) - throws IOException, ClassNotFoundException + throws IOException { ObjectOutputStream out = new ObjectOutputStream(new ByteArrayOutputStream(3000)); @@ -65,7 +67,7 @@ public static void main(String args[]) // allow writeObject to be called on any objects that // have already been serialized. These objects should be // written out by reference. - Iterator iter = A.writeObjectExtent.iterator(); + Iterator iter = A.writeObjectExtent.iterator(); while (iter.hasNext()) { out.writeObject(iter.next()); } diff --git a/test/jdk/java/io/Serializable/writeReplace/WriteReplace.java b/test/jdk/java/io/Serializable/writeReplace/WriteReplace.java index 8510487553f..3459b45b177 100644 --- a/test/jdk/java/io/Serializable/writeReplace/WriteReplace.java +++ b/test/jdk/java/io/Serializable/writeReplace/WriteReplace.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -30,6 +30,9 @@ public class WriteReplace { static class ReplaceMe implements Serializable { + private static final long serialVersionUID = 1L; + + @SuppressWarnings("serial") /* Incorrect use is being tested */ private Object obj; private boolean writeReplaceCalled = false; diff --git a/test/jdk/java/io/Serializable/wrongReturnTypes/Read.java b/test/jdk/java/io/Serializable/wrongReturnTypes/Read.java index 98d301995ff..6fc2bd505ec 100644 --- a/test/jdk/java/io/Serializable/wrongReturnTypes/Read.java +++ b/test/jdk/java/io/Serializable/wrongReturnTypes/Read.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,6 +34,7 @@ class A implements Serializable { static boolean readObjectNoDataCalled; + @SuppressWarnings("serial") /* Incorrect use is being tested */ private Object readObjectNoData() throws ObjectStreamException { readObjectNoDataCalled = true; return null; @@ -46,6 +47,7 @@ class B extends A { static boolean readObjectCalled; static boolean readResolveCalled; + @SuppressWarnings("serial") /* Incorrect use is being tested */ private Integer readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { @@ -54,6 +56,7 @@ private Integer readObject(ObjectInputStream in) return null; } + @SuppressWarnings("serial") /* Incorrect use is being tested */ private B readResolve() throws ObjectStreamException { readResolveCalled = true; return this; diff --git a/test/jdk/java/io/Serializable/wrongReturnTypes/Write.java b/test/jdk/java/io/Serializable/wrongReturnTypes/Write.java index ec3c71e7fde..f5f3405ba91 100644 --- a/test/jdk/java/io/Serializable/wrongReturnTypes/Write.java +++ b/test/jdk/java/io/Serializable/wrongReturnTypes/Write.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -43,12 +43,14 @@ class B implements Serializable { static boolean writeObjectCalled; static boolean writeReplaceCalled; + @SuppressWarnings("serial") /* Incorrect use is being tested */ private Object writeObject(ObjectOutputStream out) throws IOException { writeObjectCalled = true; out.defaultWriteObject(); return null; } + @SuppressWarnings("serial") /* Incorrect use is being tested */ private B writeReplace() throws ObjectStreamException { writeReplaceCalled = true; return this; diff --git a/test/jdk/java/lang/String/CompactString/NegativeSize.java b/test/jdk/java/lang/String/CompactString/NegativeSize.java new file mode 100644 index 00000000000..34e9ae4b435 --- /dev/null +++ b/test/jdk/java/lang/String/CompactString/NegativeSize.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2023, 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.IOException; +import java.nio.charset.StandardCharsets; + +/* + * @test + * @bug 8077559 + * @summary Tests Compact String for negative size. + * @requires vm.bits == 64 & os.maxMemory >= 4G + * @compile -encoding utf-8 NegativeSize.java + * @run main/othervm -XX:+CompactStrings -Xmx4g NegativeSize + * @run main/othervm -XX:-CompactStrings -Xmx4g NegativeSize + */ + +// In Java8: java.lang.OutOfMemoryError: Java heap space +// In Java9+: was java.lang.NegativeArraySizeException: -1894967266 +public class NegativeSize { + + static byte[] generateData() { + int asciisize = 1_200_000_000; + byte[] nonAscii = "非アスキー".getBytes(); + int nonAsciiSize = nonAscii.length; + // 1 GB + byte[] arr = new byte[asciisize + nonAsciiSize]; + for (int i=0; i result = new ArrayList<>(); - for (var client : List.of(authClient, noAuthClient)) { + for (boolean useAuth : List.of(true, false)) { for (boolean async : List.of(true, false)) { for (int code : List.of(UNAUTHORIZED, PROXY_UNAUTHORIZED)) { var srv = code == PROXY_UNAUTHORIZED ? "/proxy" : "/server"; for (var auth : List.of("/auth", "/noauth")) { var pcode = code; if (auth.equals("/noauth")) { - if (client == authClient) continue; + if (useAuth) continue; pcode = FORBIDDEN; } for (var uri : List.of(httpURI, httpsURI, http2URI, https2URI)) { - result.add(new Object[]{uri + srv + auth, pcode, async, client}); + result.add(new Object[]{uri + srv + auth, pcode, async, useAuth}); } } } @@ -242,12 +242,13 @@ protected PasswordAuthentication getPasswordAuthentication() { static final AtomicLong sleepCount = new AtomicLong(); @Test(dataProvider = "all") - void test(String uriString, int code, boolean async, HttpClient client) throws Throwable { + void test(String uriString, int code, boolean async, boolean useAuth) throws Throwable { checkSkip(); + HttpClient client = useAuth ? authClient : noAuthClient; var name = String.format("test(%s, %d, %s, %s)", uriString, code, async ? "async" : "sync", client.authenticator().isPresent() ? "authClient" : "noAuthClient"); out.printf("%n---- starting %s ----%n", name); - assert client.authenticator().isPresent() ? client == authClient : client == noAuthClient; + assert client.authenticator().isPresent() == useAuth; uriString = uriString + "/ForbiddenTest"; for (int i=0; i 1) out.printf("---- ITERATION %d%n",i); @@ -389,14 +390,17 @@ public void setup() throws Exception { public void teardown() throws Exception { authClient = noAuthClient = null; Thread.sleep(100); - AssertionError fail = TRACKER.check(500); - - proxy.stop(); - authproxy.stop(); - httpTestServer.stop(); - httpsTestServer.stop(); - http2TestServer.stop(); - https2TestServer.stop(); + AssertionError fail = TRACKER.check(1500); + try { + proxy.stop(); + authproxy.stop(); + httpTestServer.stop(); + httpsTestServer.stop(); + http2TestServer.stop(); + https2TestServer.stop(); + } finally { + if (fail != null) throw fail; + } } static class TestProxySelector extends ProxySelector { diff --git a/test/jdk/java/net/httpclient/HttpServerAdapters.java b/test/jdk/java/net/httpclient/HttpServerAdapters.java index 5147afa4f32..2b604c08c7f 100644 --- a/test/jdk/java/net/httpclient/HttpServerAdapters.java +++ b/test/jdk/java/net/httpclient/HttpServerAdapters.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, 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 @@ -207,6 +207,8 @@ public static abstract class HttpTestExchange { public abstract URI getRequestURI(); public abstract String getRequestMethod(); public abstract void close(); + public abstract InetSocketAddress getRemoteAddress(); + public abstract InetSocketAddress getLocalAddress(); public void serverPush(URI uri, HttpHeaders headers, byte[] body) { ByteArrayInputStream bais = new ByteArrayInputStream(body); serverPush(uri, headers, bais); @@ -264,6 +266,15 @@ void doFilter(Filter.Chain chain) throws IOException { } @Override public void close() { exchange.close(); } + + @Override + public InetSocketAddress getRemoteAddress() { + return exchange.getRemoteAddress(); + } + @Override + public InetSocketAddress getLocalAddress() { + return exchange.getLocalAddress(); + } @Override public URI getRequestURI() { return exchange.getRequestURI(); } @Override @@ -319,6 +330,16 @@ void doFilter(Filter.Chain filter) throws IOException { } @Override public void close() { exchange.close();} + + @Override + public InetSocketAddress getRemoteAddress() { + return exchange.getRemoteAddress(); + } + @Override + public InetSocketAddress getLocalAddress() { + return exchange.getLocalAddress(); + } + @Override public URI getRequestURI() { return exchange.getRequestURI(); } @Override diff --git a/test/jdk/java/net/httpclient/ProxySelectorTest.java b/test/jdk/java/net/httpclient/ProxySelectorTest.java index 7b4a3c8ed43..c4bbad6ebf8 100644 --- a/test/jdk/java/net/httpclient/ProxySelectorTest.java +++ b/test/jdk/java/net/httpclient/ProxySelectorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2024, 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 @@ -386,15 +386,18 @@ public void teardown() throws Exception { client = null; Thread.sleep(100); AssertionError fail = TRACKER.check(500); - - proxy.stop(); - authproxy.stop(); - httpTestServer.stop(); - proxyHttpTestServer.stop(); - authProxyHttpTestServer.stop(); - httpsTestServer.stop(); - http2TestServer.stop(); - https2TestServer.stop(); + try { + proxy.stop(); + authproxy.stop(); + httpTestServer.stop(); + proxyHttpTestServer.stop(); + authProxyHttpTestServer.stop(); + httpsTestServer.stop(); + http2TestServer.stop(); + https2TestServer.stop(); + } finally { + if (fail != null) throw fail; + } } class TestProxySelector extends ProxySelector { diff --git a/test/jdk/java/net/httpclient/Response1xxTest.java b/test/jdk/java/net/httpclient/Response1xxTest.java new file mode 100644 index 00000000000..1023fc5e04b --- /dev/null +++ b/test/jdk/java/net/httpclient/Response1xxTest.java @@ -0,0 +1,497 @@ +/* + * Copyright (c) 2022, 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.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.ProtocolException; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpTimeoutException; +import java.nio.charset.StandardCharsets; +import java.time.Duration; + +import javax.net.ssl.SSLContext; + +import jdk.test.lib.net.SimpleSSLContext; +import jdk.test.lib.net.URIBuilder; +import org.testng.Assert; +import org.testng.annotations.AfterClass; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * @test + * @bug 8292044 + * @summary Tests behaviour of HttpClient when server responds with 102 or 103 status codes + * @modules java.base/sun.net.www.http + * java.net.http/jdk.internal.net.http.common + * java.net.http/jdk.internal.net.http.frame + * java.net.http/jdk.internal.net.http.hpack + * java.logging + * jdk.httpserver + * @library /test/lib http2/server + * @build Http2TestServer HttpServerAdapters SpecialHeadersTest + * @build jdk.test.lib.net.SimpleSSLContext + * @run testng/othervm -Djdk.internal.httpclient.debug=true + * * -Djdk.httpclient.HttpClient.log=headers,requests,responses,errors Response1xxTest + */ +public class Response1xxTest implements HttpServerAdapters { + private static final String EXPECTED_RSP_BODY = "Hello World"; + + private ServerSocket serverSocket; + private Http11Server server; + private String http1RequestURIBase; + + + private HttpTestServer http2Server; // h2c + private String http2RequestURIBase; + + + private SSLContext sslContext; + private HttpTestServer https2Server; // h2 + private String https2RequestURIBase; + + private final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; + + @BeforeClass + public void setup() throws Exception { + serverSocket = new ServerSocket(0, 0, InetAddress.getLoopbackAddress()); + server = new Http11Server(serverSocket); + new Thread(server).start(); + http1RequestURIBase = URIBuilder.newBuilder().scheme("http").loopback() + .port(serverSocket.getLocalPort()).build().toString(); + + http2Server = HttpTestServer.of(new Http2TestServer("localhost", false, 0)); + http2Server.addHandler(new Http2Handler(), "/http2/102"); + http2Server.addHandler(new Http2Handler(), "/http2/103"); + http2Server.addHandler(new Http2Handler(), "/http2/100"); + http2Server.addHandler(new Http2Handler(), "/http2/101"); + http2Server.addHandler(new OKHandler(), "/http2/200"); + http2Server.addHandler(new OnlyInformationalHandler(), "/http2/only-informational"); + http2RequestURIBase = URIBuilder.newBuilder().scheme("http").loopback() + .port(http2Server.getAddress().getPort()) + .path("/http2").build().toString(); + + http2Server.start(); + System.out.println("Started HTTP2 server at " + http2Server.getAddress()); + + sslContext = new SimpleSSLContext().get(); + if (sslContext == null) { + throw new AssertionError("Unexpected null sslContext"); + } + https2Server = HttpTestServer.of(new Http2TestServer("localhost", + true, sslContext)); + https2Server.addHandler(new Http2Handler(), "/http2/101"); + https2RequestURIBase = URIBuilder.newBuilder().scheme("https").loopback() + .port(https2Server.getAddress().getPort()) + .path("/http2").build().toString(); + https2Server.start(); + System.out.println("Started (https) HTTP2 server at " + https2Server.getAddress()); + + } + + @AfterClass + public void teardown() throws Throwable { + try { + assertNoOutstandingClientOps(); + } finally { + if (server != null) { + server.stop = true; + System.out.println("(HTTP 1.1) Server stop requested"); + } + if (serverSocket != null) { + serverSocket.close(); + System.out.println("Closed (HTTP 1.1) server socket"); + } + if (http2Server != null) { + http2Server.stop(); + System.out.println("Stopped HTTP2 server"); + } + if (https2Server != null) { + https2Server.stop(); + System.out.println("Stopped (https) HTTP2 server"); + } + } + } + + private static final class Http11Server implements Runnable { + private static final int CONTENT_LENGTH = EXPECTED_RSP_BODY.getBytes(StandardCharsets.UTF_8).length; + + private static final String HTTP_1_1_RSP_200 = "HTTP/1.1 200 OK\r\n" + + "Content-Length: " + CONTENT_LENGTH + "\r\n\r\n" + + EXPECTED_RSP_BODY; + + private static final String REQ_LINE_FOO = "GET /test/foo HTTP/1.1\r\n"; + private static final String REQ_LINE_BAR = "GET /test/bar HTTP/1.1\r\n"; + private static final String REQ_LINE_HELLO = "GET /test/hello HTTP/1.1\r\n"; + private static final String REQ_LINE_BYE = "GET /test/bye HTTP/1.1\r\n"; + + + private final ServerSocket serverSocket; + private volatile boolean stop; + + private Http11Server(final ServerSocket serverSocket) { + this.serverSocket = serverSocket; + } + + @Override + public void run() { + System.out.println("Server running at " + serverSocket); + while (!stop) { + Socket socket = null; + try { + // accept a connection + socket = serverSocket.accept(); + System.out.println("Accepted connection from client " + socket); + // read request + final String requestLine; + try { + requestLine = readRequestLine(socket); + } catch (Throwable t) { + // ignore connections from potential rogue client + System.err.println("Ignoring connection/request from client " + socket + + " due to exception:"); + t.printStackTrace(); + // close the socket + safeClose(socket); + continue; + } + System.out.println("Received following request line from client " + socket + + " :\n" + requestLine); + final int informationalResponseCode; + if (requestLine.startsWith(REQ_LINE_FOO)) { + // we will send intermediate/informational 102 response + informationalResponseCode = 102; + } else if (requestLine.startsWith(REQ_LINE_BAR)) { + // we will send intermediate/informational 103 response + informationalResponseCode = 103; + } else if (requestLine.startsWith(REQ_LINE_HELLO)) { + // we will send intermediate/informational 100 response + informationalResponseCode = 100; + } else if (requestLine.startsWith(REQ_LINE_BYE)) { + // we will send intermediate/informational 101 response + informationalResponseCode = 101; + } else { + // unexpected client. ignore and close the client + System.err.println("Ignoring unexpected request from client " + socket); + safeClose(socket); + continue; + } + try (final OutputStream os = socket.getOutputStream()) { + // send informational response headers a few times (spec allows them to + // be sent multiple times) + for (int i = 0; i < 3; i++) { + // send 1xx response header + if (informationalResponseCode == 101) { + os.write(("HTTP/1.1 " + informationalResponseCode + "\r\n" + + "Connection: upgrade\r\n" + + "Upgrade: websocket\r\n\r\n") + .getBytes(StandardCharsets.UTF_8)); + } else { + os.write(("HTTP/1.1 " + informationalResponseCode + "\r\n\r\n") + .getBytes(StandardCharsets.UTF_8)); + } + os.flush(); + System.out.println("Sent response code " + informationalResponseCode + + " to client " + socket); + } + // now send a final response + System.out.println("Now sending 200 response code to client " + socket); + os.write(HTTP_1_1_RSP_200.getBytes(StandardCharsets.UTF_8)); + os.flush(); + System.out.println("Sent 200 response code to client " + socket); + } + } catch (Throwable t) { + // close the client connection + safeClose(socket); + // continue accepting any other client connections until we are asked to stop + System.err.println("Ignoring exception in server:"); + t.printStackTrace(); + } + } + } + + static String readRequestLine(final Socket sock) throws IOException { + final InputStream is = sock.getInputStream(); + final StringBuilder sb = new StringBuilder(""); + byte[] buf = new byte[1024]; + while (!sb.toString().endsWith("\r\n\r\n")) { + final int numRead = is.read(buf); + if (numRead == -1) { + return sb.toString(); + } + final String part = new String(buf, 0, numRead, StandardCharsets.ISO_8859_1); + sb.append(part); + } + return sb.toString(); + } + + private static void safeClose(final Socket socket) { + try { + socket.close(); + } catch (Throwable t) { + // ignore + } + } + } + + private static class Http2Handler implements HttpTestHandler { + + @Override + public void handle(final HttpTestExchange exchange) throws IOException { + final URI requestURI = exchange.getRequestURI(); + final int informationResponseCode; + if (requestURI.getPath().endsWith("/102")) { + informationResponseCode = 102; + } else if (requestURI.getPath().endsWith("/103")) { + informationResponseCode = 103; + } else if (requestURI.getPath().endsWith("/100")) { + informationResponseCode = 100; + } else if (requestURI.getPath().endsWith("/101")) { + informationResponseCode = 101; + } else { + // unexpected request + System.err.println("Unexpected request " + requestURI + " from client " + + exchange.getRemoteAddress()); + exchange.sendResponseHeaders(400, -1); + return; + } + // send informational response headers a few times (spec allows them to + // be sent multiple times) + for (int i = 0; i < 3; i++) { + exchange.sendResponseHeaders(informationResponseCode, -1); + System.out.println("Sent " + informationResponseCode + " response code from H2 server"); + } + // now send 200 response + try { + final byte[] body = EXPECTED_RSP_BODY.getBytes(StandardCharsets.UTF_8); + exchange.sendResponseHeaders(200, body.length); + System.out.println("Sent 200 response from H2 server"); + try (OutputStream os = exchange.getResponseBody()) { + os.write(body); + } + System.out.println("Sent response body from H2 server"); + } catch (Throwable e) { + System.err.println("Failed to send response from HTTP2 handler:"); + e.printStackTrace(); + throw e; + } + } + } + + private static class OnlyInformationalHandler implements HttpTestHandler { + + @Override + public void handle(final HttpTestExchange exchange) throws IOException { + // we only send informational response and then return + for (int i = 0; i < 5; i++) { + exchange.sendResponseHeaders(102, -1); + System.out.println("Sent 102 response code from H2 server"); + // wait for a while before sending again + try { + Thread.sleep(2000); + } catch (InterruptedException e) { + // just return + System.err.println("Handler thread interrupted"); + } + } + } + } + + private static class OKHandler implements HttpTestHandler { + + @Override + public void handle(final HttpTestExchange exchange) throws IOException { + exchange.sendResponseHeaders(200, -1); + } + } + + /** + * Tests that when a HTTP/1.1 server sends intermediate 1xx response codes and then the final + * response, the client (internally) will ignore those intermediate informational response codes + * and only return the final response to the application + */ + @Test + public void test1xxForHTTP11() throws Exception { + final HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_1_1) + .proxy(HttpClient.Builder.NO_PROXY).build(); + TRACKER.track(client); + final URI[] requestURIs = new URI[]{ + new URI(http1RequestURIBase + "/test/foo"), + new URI(http1RequestURIBase + "/test/bar"), + new URI(http1RequestURIBase + "/test/hello")}; + for (final URI requestURI : requestURIs) { + final HttpRequest request = HttpRequest.newBuilder(requestURI).build(); + System.out.println("Issuing request to " + requestURI); + final HttpResponse response = client.send(request, + HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + Assert.assertEquals(response.version(), HttpClient.Version.HTTP_1_1, + "Unexpected HTTP version in response"); + Assert.assertEquals(response.statusCode(), 200, "Unexpected response code"); + Assert.assertEquals(response.body(), EXPECTED_RSP_BODY, "Unexpected response body"); + } + } + + /** + * Tests that when a HTTP2 server sends intermediate 1xx response codes and then the final + * response, the client (internally) will ignore those intermediate informational response codes + * and only return the final response to the application + */ + @Test + public void test1xxForHTTP2() throws Exception { + final HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .proxy(HttpClient.Builder.NO_PROXY).build(); + TRACKER.track(client); + final URI[] requestURIs = new URI[]{ + new URI(http2RequestURIBase + "/102"), + new URI(http2RequestURIBase + "/103"), + new URI(http2RequestURIBase + "/100")}; + for (final URI requestURI : requestURIs) { + final HttpRequest request = HttpRequest.newBuilder(requestURI).build(); + System.out.println("Issuing request to " + requestURI); + final HttpResponse response = client.send(request, + HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + Assert.assertEquals(response.version(), HttpClient.Version.HTTP_2, + "Unexpected HTTP version in response"); + Assert.assertEquals(response.statusCode(), 200, "Unexpected response code"); + Assert.assertEquals(response.body(), EXPECTED_RSP_BODY, "Unexpected response body"); + } + } + + + /** + * Tests that when a request is issued with a specific request timeout and the server + * responds with intermediate 1xx response code but doesn't respond with a final response within + * the timeout duration, then the application fails with a request timeout + */ + @Test + public void test1xxRequestTimeout() throws Exception { + final HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .proxy(HttpClient.Builder.NO_PROXY).build(); + TRACKER.track(client); + final URI requestURI = new URI(http2RequestURIBase + "/only-informational"); + final Duration requestTimeout = Duration.ofSeconds(2); + final HttpRequest request = HttpRequest.newBuilder(requestURI).timeout(requestTimeout) + .build(); + System.out.println("Issuing request to " + requestURI); + // we expect the request to timeout + Assert.assertThrows(HttpTimeoutException.class, () -> { + client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8)); + }); + } + + /** + * Tests that when the HTTP/1.1 server sends a 101 response when the request hasn't asked + * for an "Upgrade" then the request fails. + */ + @Test + public void testHTTP11Unexpected101() throws Exception { + final HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_1_1) + .proxy(HttpClient.Builder.NO_PROXY).build(); + TRACKER.track(client); + final URI requestURI = new URI(http1RequestURIBase + "/test/bye"); + final HttpRequest request = HttpRequest.newBuilder(requestURI).build(); + System.out.println("Issuing request to " + requestURI); + // we expect the request to fail because the server sent an unexpected 101 + Assert.assertThrows(ProtocolException.class, + () -> client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8))); + } + + + /** + * Tests that when the HTTP2 server (over HTTPS) sends a 101 response when the request + * hasn't asked for an "Upgrade" then the request fails. + */ + @Test + public void testSecureHTTP2Unexpected101() throws Exception { + final HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .sslContext(sslContext) + .proxy(HttpClient.Builder.NO_PROXY).build(); + TRACKER.track(client); + final URI requestURI = new URI(https2RequestURIBase + "/101"); + final HttpRequest request = HttpRequest.newBuilder(requestURI).build(); + System.out.println("Issuing request to " + requestURI); + // we expect the request to fail because the server sent an unexpected 101 + // Backport note: Later JDK versions (e.g. 17 or 21) throw a ProtocolException. + Assert.assertThrows(IOException.class, + () -> client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8))); + } + + /** + * Tests that when the HTTP2 server (over plain HTTP) sends a 101 response when the request + * hasn't asked for an "Upgrade" then the request fails. + */ + @Test + public void testPlainHTTP2Unexpected101() throws Exception { + final HttpClient client = HttpClient.newBuilder() + .version(HttpClient.Version.HTTP_2) + .proxy(HttpClient.Builder.NO_PROXY).build(); + TRACKER.track(client); + // when using HTTP2 version against a "http://" (non-secure) URI + // the HTTP client (implementation) internally initiates a HTTP/1.1 connection + // and then does an "Upgrade:" to "h2c". This it does when there isn't already a + // H2 connection against the target/destination server. So here we initiate a dummy request + // using the client instance against the same target server and just expect it to return + // back successfully. Once that connection is established (and internally pooled), the client + // will then reuse that connection and won't issue an "Upgrade:" and thus we can then + // start our testing + warmupH2Client(client); + // start the actual testing + final URI requestURI = new URI(http2RequestURIBase + "/101"); + final HttpRequest request = HttpRequest.newBuilder(requestURI).build(); + System.out.println("Issuing request to " + requestURI); + // we expect the request to fail because the server sent an unexpected 101 + Assert.assertThrows(ProtocolException.class, + () -> client.send(request, HttpResponse.BodyHandlers.ofString(StandardCharsets.UTF_8))); + } + + // sends a request and expects a 200 response back + private void warmupH2Client(final HttpClient client) throws Exception { + final URI requestURI = new URI(http2RequestURIBase + "/200"); + final HttpRequest request = HttpRequest.newBuilder(requestURI).build(); + System.out.println("Issuing (warmup) request to " + requestURI); + final HttpResponse response = client.send(request, HttpResponse.BodyHandlers.discarding()); + Assert.assertEquals(response.statusCode(), 200, "Unexpected response code"); + } + + // verifies that the HttpClient being tracked has no outstanding operations + private void assertNoOutstandingClientOps() throws AssertionError { + System.gc(); + final AssertionError refCheckFailure = TRACKER.check(1000); + if (refCheckFailure != null) { + throw refCheckFailure; + } + // successful test completion + } +} diff --git a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsInputStreamCustom.java b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsInputStreamCustom.java index c3801a0c429..95671d6a3ff 100644 --- a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsInputStreamCustom.java +++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsInputStreamCustom.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8229822 * @summary Tests what happens when push promise handlers and their * response body handlers and subscribers throw unexpected exceptions. * @library /test/lib http2/server diff --git a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsInputStreamIO.java b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsInputStreamIO.java index f11c31421a1..7f22bdf4961 100644 --- a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsInputStreamIO.java +++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsInputStreamIO.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8229822 * @summary Tests what happens when push promise handlers and their * response body handlers and subscribers throw unexpected exceptions. * @library /test/lib http2/server diff --git a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsLinesCustom.java b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsLinesCustom.java index 847bc382838..e17a72a21dc 100644 --- a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsLinesCustom.java +++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsLinesCustom.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8229822 * @summary Tests what happens when push promise handlers and their * response body handlers and subscribers throw unexpected exceptions. * @library /test/lib http2/server diff --git a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsLinesIO.java b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsLinesIO.java index 7b7ffab49a2..678a58530c1 100644 --- a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsLinesIO.java +++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsLinesIO.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8229822 * @summary Tests what happens when push promise handlers and their * response body handlers and subscribers throw unexpected exceptions. * @library /test/lib http2/server diff --git a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsStringCustom.java b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsStringCustom.java index eb6f2a7c8f9..be94c2fa4ff 100644 --- a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsStringCustom.java +++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsStringCustom.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8229822 * @summary Tests what happens when push promise handlers and their * response body handlers and subscribers throw unexpected exceptions. * @library /test/lib http2/server diff --git a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsStringIO.java b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsStringIO.java index 24d38f1a6df..a7120964869 100644 --- a/test/jdk/java/net/httpclient/ThrowingPushPromisesAsStringIO.java +++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesAsStringIO.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8229822 * @summary Tests what happens when push promise handlers and their * response body handlers and subscribers throw unexpected exceptions. * @library /test/lib http2/server diff --git a/test/jdk/java/net/httpclient/ThrowingPushPromisesSanity.java b/test/jdk/java/net/httpclient/ThrowingPushPromisesSanity.java index b2ffd374d2e..d064c322599 100644 --- a/test/jdk/java/net/httpclient/ThrowingPushPromisesSanity.java +++ b/test/jdk/java/net/httpclient/ThrowingPushPromisesSanity.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8229822 * @summary Tests what happens when push promise handlers and their * response body handlers and subscribers throw unexpected exceptions. * @library /test/lib http2/server diff --git a/test/jdk/java/net/httpclient/http2/BadHeadersTest.java b/test/jdk/java/net/httpclient/http2/BadHeadersTest.java index 2e4765fdf1b..ce7adb25b58 100644 --- a/test/jdk/java/net/httpclient/http2/BadHeadersTest.java +++ b/test/jdk/java/net/httpclient/http2/BadHeadersTest.java @@ -23,6 +23,7 @@ /* * @test + * @bug 8303965 * @modules java.base/sun.net.www.http * java.net.http/jdk.internal.net.http.common * java.net.http/jdk.internal.net.http.frame @@ -201,20 +202,26 @@ void testAsync(String uri, // Assertions based on implementation specific detail messages. Keep in // sync with implementation. static void assertDetailMessage(Throwable throwable, int iterationIndex) { - assertTrue(throwable instanceof IOException, - "Expected IOException, got, " + throwable); - assertTrue(throwable.getMessage().contains("protocol error"), - "Expected \"protocol error\" in: " + throwable.getMessage()); - - if (iterationIndex == 0) { // unknown - assertTrue(throwable.getMessage().contains("Unknown pseudo-header"), - "Expected \"Unknown pseudo-header\" in: " + throwable.getMessage()); - } else if (iterationIndex == 4) { // unexpected - assertTrue(throwable.getMessage().contains(" Unexpected pseudo-header"), - "Expected \" Unexpected pseudo-header\" in: " + throwable.getMessage()); - } else { - assertTrue(throwable.getMessage().contains("Bad header"), - "Expected \"Bad header\" in: " + throwable.getMessage()); + try { + assertTrue(throwable instanceof IOException, + "Expected IOException, got, " + throwable); + assertTrue(throwable.getMessage().contains("malformed response"), + "Expected \"malformed response\" in: " + throwable.getMessage()); + + if (iterationIndex == 0) { // unknown + assertTrue(throwable.getMessage().contains("Unknown pseudo-header"), + "Expected \"Unknown pseudo-header\" in: " + throwable.getMessage()); + } else if (iterationIndex == 4) { // unexpected + assertTrue(throwable.getMessage().contains(" Unexpected pseudo-header"), + "Expected \" Unexpected pseudo-header\" in: " + throwable.getMessage()); + } else { + assertTrue(throwable.getMessage().contains("Bad header"), + "Expected \"Bad header\" in: " + throwable.getMessage()); + } + } catch (AssertionError e) { + System.out.println("Exception does not match expectation: " + throwable); + throwable.printStackTrace(System.out); + throw e; } } diff --git a/test/jdk/java/net/httpclient/http2/ConnectionReuseTest.java b/test/jdk/java/net/httpclient/http2/ConnectionReuseTest.java new file mode 100644 index 00000000000..e60f2033deb --- /dev/null +++ b/test/jdk/java/net/httpclient/http2/ConnectionReuseTest.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2023, 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.IOException; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import javax.net.ssl.SSLContext; + +import jdk.test.lib.net.IPSupport; +import jdk.test.lib.net.SimpleSSLContext; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.Assumptions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; +import static java.net.http.HttpClient.Builder.NO_PROXY; +import static java.net.http.HttpClient.Version.HTTP_2; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +/* + * @test + * @bug 8305906 + * @summary verify that the HttpClient pools and reuses a connection for HTTP/2 requests + * @library /test/lib server/ ../ + * @build jdk.test.lib.net.SimpleSSLContext HttpServerAdapters + * ReferenceTracker jdk.test.lib.net.IPSupport + * @modules java.net.http/jdk.internal.net.http.common + * java.net.http/jdk.internal.net.http.frame + * java.net.http/jdk.internal.net.http.hpack + * java.logging + * java.base/sun.net.www.http + * java.base/sun.net.www + * java.base/sun.net + * + * @run junit/othervm ConnectionReuseTest + * @run junit/othervm -Djava.net.preferIPv6Addresses=true ConnectionReuseTest + */ +public class ConnectionReuseTest implements HttpServerAdapters { + + private static SSLContext sslContext; + private static HttpTestServer http2_Server; // h2 server over HTTP + private static HttpTestServer https2_Server; // h2 server over HTTPS + + @BeforeAll + public static void beforeAll() throws Exception { + if (IPSupport.preferIPv6Addresses()) { + IPSupport.printPlatformSupport(System.err); // for debug purposes + // this test is run with -Djava.net.preferIPv6Addresses=true, so skip (all) tests + // if IPv6 isn't supported on this host + Assumptions.assumeTrue(IPSupport.hasIPv6(), "Skipping tests - IPv6 is not supported"); + } + sslContext = new SimpleSSLContext().get(); + assertNotNull(sslContext, "Unexpected null sslContext"); + + http2_Server = HttpTestServer.of( + new Http2TestServer("localhost", false, 0)); + http2_Server.addHandler(new Handler(), "/"); + http2_Server.start(); + System.out.println("Started HTTP v2 server at " + http2_Server.serverAuthority()); + + https2_Server = HttpTestServer.of( + new Http2TestServer("localhost", true, sslContext)); + https2_Server.addHandler(new Handler(), "/"); + https2_Server.start(); + System.out.println("Started HTTPS v2 server at " + https2_Server.serverAuthority()); + } + + @AfterAll + public static void afterAll() { + if (https2_Server != null) { + System.out.println("Stopping server " + https2_Server); + https2_Server.stop(); + } + if (http2_Server != null) { + System.out.println("Stopping server " + http2_Server); + http2_Server.stop(); + } + } + + private static Stream requestURIs() throws Exception { + final List arguments = new ArrayList<>(); + // h2 over HTTPS + arguments.add(Arguments.of(new URI("https://" + https2_Server.serverAuthority() + "/"))); + // h2 over HTTP + arguments.add(Arguments.of(new URI("http://" + http2_Server.serverAuthority() + "/"))); + if (IPSupport.preferIPv6Addresses()) { + if (http2_Server.getAddress().getAddress().isLoopbackAddress()) { + // h2 over HTTP, use the short form of the host, in the request URI + arguments.add(Arguments.of(new URI("http://[::1]:" + + http2_Server.getAddress().getPort() + "/"))); + } + } + return arguments.stream(); + } + + /** + * Uses a single instance of a HttpClient and issues multiple requests to {@code requestURI} + * and expects that each of the request internally uses the same connection + */ + @ParameterizedTest + @MethodSource("requestURIs") + public void testConnReuse(final URI requestURI) throws Throwable { + final HttpClient.Builder builder = HttpClient.newBuilder() + .proxy(NO_PROXY).sslContext(sslContext); + final HttpRequest req = HttpRequest.newBuilder().uri(requestURI) + .GET().version(HTTP_2).build(); + final ReferenceTracker tracker = ReferenceTracker.INSTANCE; + Throwable testFailure = null; + HttpClient client = tracker.track(builder.build()); + try { + String clientConnAddr = null; + for (int i = 1; i <= 5; i++) { + System.out.println("Issuing request(" + i + ") " + req); + final HttpResponse resp = client.send(req, BodyHandlers.ofString()); + assertEquals(200, resp.statusCode(), "unexpected response code"); + final String respBody = resp.body(); + System.out.println("Server side handler responded to a request from " + respBody); + assertNotEquals(Handler.UNKNOWN_CLIENT_ADDR, respBody, + "server handler couldn't determine client address in request"); + if (i == 1) { + // for the first request we just keep track of the client connection address + // that got used for this request + clientConnAddr = respBody; + } else { + // verify that the client connection used to issue the request is the same + // as the previous request's client connection + assertEquals(clientConnAddr, respBody, "HttpClient unexpectedly used a" + + " different connection for request(" + i + ")"); + } + } + } catch (Throwable t) { + testFailure = t; + } finally { + // dereference the client to allow the tracker to verify the resources + // have been released + client = null; + // wait for the client to be shutdown + final AssertionError trackerFailure = tracker.check(2000); + if (testFailure != null) { + if (trackerFailure != null) { + // add the failure reported by the tracker as a suppressed + // exception and throw the original test failure + testFailure.addSuppressed(trackerFailure); + } + throw testFailure; + } + if (trackerFailure != null) { + // the test itself didn't fail but the tracker check failed. + // fail the test with this exception + throw trackerFailure; + } + } + } + + private static final class Handler implements HttpTestHandler { + + private static final String UNKNOWN_CLIENT_ADDR = "unknown"; + + @Override + public void handle(final HttpTestExchange t) throws IOException { + final InetSocketAddress clientAddr = t.getRemoteAddress(); + System.out.println("Handling request " + t.getRequestURI() + " from " + clientAddr); + // we write out the client address into the response body + final byte[] responseBody = clientAddr == null + ? UNKNOWN_CLIENT_ADDR.getBytes(StandardCharsets.UTF_8) + : clientAddr.toString().getBytes(StandardCharsets.UTF_8); + t.sendResponseHeaders(200, responseBody.length); + try (final OutputStream os = t.getResponseBody()) { + os.write(responseBody); + } + } + } +} diff --git a/test/jdk/java/net/httpclient/http2/ContinuationFrameTest.java b/test/jdk/java/net/httpclient/http2/ContinuationFrameTest.java index ac692f478c8..0ca77044296 100644 --- a/test/jdk/java/net/httpclient/http2/ContinuationFrameTest.java +++ b/test/jdk/java/net/httpclient/http2/ContinuationFrameTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ * java.net.http/jdk.internal.net.http.frame * java.net.http/jdk.internal.net.http.hpack * @library /test/lib server + * @compile ../ReferenceTracker.java * @build Http2TestServer * @build jdk.test.lib.net.SimpleSSLContext * @run testng/othervm ContinuationFrameTest @@ -72,6 +73,9 @@ public class ContinuationFrameTest { Http2TestServer https2TestServer; // HTTP/2 ( h2 ) String http2URI; String https2URI; + String noBodyhttp2URI; + String noBodyhttps2URI; + final ReferenceTracker TRACKER = ReferenceTracker.INSTANCE; /** * A function that returns a list of 1) a HEADERS frame ( with an empty @@ -87,6 +91,23 @@ public class ContinuationFrameTest { return List.of(hf, cf); }; + /** + * A function that returns a list of 1) a HEADERS frame with END_STREAM + * ( and with an empty payload ), and 2) two CONTINUATION frames,the first + * is empty and the second contains headers and the END_HEADERS flag + */ + static BiFunction,List> twoContinuation = + (Integer streamid, List encodedHeaders) -> { + List empty = List.of(ByteBuffer.wrap(new byte[0])); + HeadersFrame hf = new HeadersFrame(streamid, HeaderFrame.END_STREAM, empty); + ContinuationFrame cf = new ContinuationFrame(streamid, 0,empty); + ContinuationFrame cf1 = new ContinuationFrame(streamid, + HeaderFrame.END_HEADERS, + encodedHeaders); + + return List.of(hf, cf, cf1); + }; + /** * A function that returns a list of a HEADERS frame followed by a number of * CONTINUATION frames. Each frame contains just a single byte of payload. @@ -112,15 +133,20 @@ public class ContinuationFrameTest { @DataProvider(name = "variants") public Object[][] variants() { return new Object[][] { - { http2URI, false, oneContinuation }, - { https2URI, false, oneContinuation }, - { http2URI, true, oneContinuation }, - { https2URI, true, oneContinuation }, - - { http2URI, false, byteAtATime }, - { https2URI, false, byteAtATime }, - { http2URI, true, byteAtATime }, - { https2URI, true, byteAtATime }, + { http2URI, false, oneContinuation }, + { https2URI, false, oneContinuation }, + { http2URI, true, oneContinuation }, + { https2URI, true, oneContinuation }, + + { noBodyhttp2URI, false, twoContinuation }, + { noBodyhttp2URI, true, twoContinuation }, + { noBodyhttps2URI, false, twoContinuation }, + { noBodyhttps2URI, true, twoContinuation }, + + { http2URI, false, byteAtATime }, + { https2URI, false, byteAtATime }, + { http2URI, true, byteAtATime }, + { https2URI, true, byteAtATime }, }; } @@ -136,8 +162,13 @@ void test(String uri, HttpClient client = null; for (int i=0; i< ITERATION_COUNT; i++) { - if (!sameClient || client == null) - client = HttpClient.newBuilder().sslContext(sslContext).build(); + if (!sameClient || client == null) { + client = HttpClient.newBuilder() + .proxy(HttpClient.Builder.NO_PROXY) + .sslContext(sslContext) + .build(); + TRACKER.track(client); + } HttpRequest request = HttpRequest.newBuilder(URI.create(uri)) .POST(BodyPublishers.ofString("Hello there!")) @@ -149,6 +180,13 @@ void test(String uri, resp = client.sendAsync(request, BodyHandlers.ofString()).join(); } + if(uri.contains("nobody")) { + out.println("Got response: " + resp); + assertTrue(resp.statusCode() == 204, + "Expected 204, got:" + resp.statusCode()); + assertEquals(resp.version(), HTTP_2); + continue; + } out.println("Got response: " + resp); out.println("Got body: " + resp.body()); assertTrue(resp.statusCode() == 200, @@ -166,13 +204,17 @@ public void setup() throws Exception { http2TestServer = new Http2TestServer("localhost", false, 0); http2TestServer.addHandler(new Http2EchoHandler(), "/http2/echo"); + http2TestServer.addHandler(new Http2NoBodyHandler(), "/http2/nobody"); int port = http2TestServer.getAddress().getPort(); http2URI = "http://localhost:" + port + "/http2/echo"; + noBodyhttp2URI = "http://localhost:" + port + "/http2/nobody"; https2TestServer = new Http2TestServer("localhost", true, sslContext); https2TestServer.addHandler(new Http2EchoHandler(), "/https2/echo"); + https2TestServer.addHandler(new Http2NoBodyHandler(), "/https2/nobody"); port = https2TestServer.getAddress().getPort(); https2URI = "https://localhost:" + port + "/https2/echo"; + noBodyhttps2URI = "https://localhost:" + port + "/https2/nobody"; // Override the default exchange supplier with a custom one to enable // particular test scenarios @@ -185,8 +227,15 @@ public void setup() throws Exception { @AfterTest public void teardown() throws Exception { - http2TestServer.stop(); - https2TestServer.stop(); + AssertionError fail = TRACKER.check(500); + try { + http2TestServer.stop(); + https2TestServer.stop(); + } finally { + if (fail != null) { + throw fail; + } + } } static class Http2EchoHandler implements Http2Handler { @@ -204,6 +253,17 @@ public void handle(Http2TestExchange t) throws IOException { } } + static class Http2NoBodyHandler implements Http2Handler { + @Override + public void handle(Http2TestExchange t) throws IOException { + try (InputStream is = t.getRequestBody(); + OutputStream os = t.getResponseBody()) { + byte[] bytes = is.readAllBytes(); + t.sendResponseHeaders(204, -1); + } + } + } + // A custom Http2TestExchangeImpl that overrides sendResponseHeaders to // allow headers to be sent with a number of CONTINUATION frames. static class CFTHttp2TestExchange extends Http2TestExchangeImpl { @@ -225,7 +285,7 @@ static void setHeaderFrameSupplier(BiFunction,List 0 || responseLength < 0) { + if (responseLength != 0 && rCode != 204) { long clen = responseLength > 0 ? responseLength : 0; rspheadersBuilder.setHeader("Content-length", Long.toString(clen)); } @@ -236,10 +296,8 @@ public void sendResponseHeaders(int rCode, long responseLength) throws IOExcepti List headerFrames = headerFrameSupplier.apply(streamid, encodeHeaders); assert headerFrames.size() > 0; // there must always be at least 1 - if (responseLength < 0) { - headerFrames.get(headerFrames.size() -1).setFlag(HeadersFrame.END_STREAM); + if(headerFrames.get(0).getFlag(HeaderFrame.END_STREAM)) os.closeInternal(); - } for (Http2Frame f : headerFrames) conn.outputQ.put(f); diff --git a/test/jdk/java/net/httpclient/http2/PushPromiseContinuation.java b/test/jdk/java/net/httpclient/http2/PushPromiseContinuation.java new file mode 100644 index 00000000000..7eb21656bef --- /dev/null +++ b/test/jdk/java/net/httpclient/http2/PushPromiseContinuation.java @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2022, 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 8263031 + * @summary Tests that the HttpClient can correctly receive a Push Promise + * Frame with the END_HEADERS flag unset followed by one or more + * Continuation Frames. + * @library /test/lib server + * @build jdk.test.lib.net.SimpleSSLContext + * @modules java.base/sun.net.www.http + * java.net.http/jdk.internal.net.http.common + * java.net.http/jdk.internal.net.http.frame + * java.net.http/jdk.internal.net.http.hpack + * @run testng/othervm PushPromiseContinuation + */ + + +import jdk.internal.net.http.common.HttpHeadersBuilder; +import jdk.internal.net.http.frame.ContinuationFrame; +import jdk.internal.net.http.frame.HeaderFrame; +import org.testng.TestException; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.Test; + +import javax.net.ssl.SSLSession; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.ProtocolException; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpHeaders; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.function.BiPredicate; + +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.testng.Assert.*; + +public class PushPromiseContinuation { + + static volatile HttpHeaders testHeaders; + static volatile HttpHeadersBuilder testHeadersBuilder; + static volatile int continuationCount; + static final String mainPromiseBody = "Main Promise Body"; + static final String mainResponseBody = "Main Response Body"; + Http2TestServer server; + URI uri; + + // Set up simple client-side push promise handler + ConcurrentMap>> pushPromiseMap = new ConcurrentHashMap<>(); + HttpResponse.PushPromiseHandler pph = (initial, pushRequest, acceptor) -> { + HttpResponse.BodyHandler s = HttpResponse.BodyHandlers.ofString(UTF_8); + pushPromiseMap.put(pushRequest, acceptor.apply(s)); + }; + + @BeforeMethod + public void beforeMethod() { + pushPromiseMap = new ConcurrentHashMap<>(); + } + + @BeforeTest + public void setup() throws Exception { + server = new Http2TestServer(false, 0); + server.addHandler(new ServerPushHandler(), "/"); + + // Need to have a custom exchange supplier to manage the server's push + // promise with continuation flow + server.setExchangeSupplier(Http2PushPromiseContinuationExchangeImpl::new); + + System.err.println("PushPromiseContinuation: Server listening on port " + server.getAddress().getPort()); + server.start(); + int port = server.getAddress().getPort(); + uri = new URI("http://localhost:" + port + "/"); + } + + @AfterTest + public void teardown() { + pushPromiseMap = null; + server.stop(); + } + + /** + * Tests that when the client receives PushPromise Frame with the END_HEADERS + * flag set to 0x0 and subsequently receives a continuation frame, no exception + * is thrown and all headers from the PushPromise and Continuation Frames sent + * by the server arrive at the client. + */ + @Test + public void testOneContinuation() { + continuationCount = 1; + HttpClient client = HttpClient.newHttpClient(); + + // Carry out request + HttpRequest hreq = HttpRequest.newBuilder(uri).version(HttpClient.Version.HTTP_2).GET().build(); + CompletableFuture> cf = + client.sendAsync(hreq, HttpResponse.BodyHandlers.ofString(UTF_8), pph); + HttpResponse resp = cf.join(); + + // Verify results + verify(resp); + } + + /** + * Same as above, but tests for the case where two Continuation Frames are sent + * with the END_HEADERS flag set only on the last frame. + */ + @Test + public void testTwoContinuations() { + continuationCount = 2; + HttpClient client = HttpClient.newHttpClient(); + + // Carry out request + HttpRequest hreq = HttpRequest.newBuilder(uri).version(HttpClient.Version.HTTP_2).GET().build(); + CompletableFuture> cf = + client.sendAsync(hreq, HttpResponse.BodyHandlers.ofString(UTF_8), pph); + HttpResponse resp = cf.join(); + + // Verify results + verify(resp); + } + + @Test + public void testThreeContinuations() { + continuationCount = 3; + HttpClient client = HttpClient.newHttpClient(); + + // Carry out request + HttpRequest hreq = HttpRequest.newBuilder(uri).version(HttpClient.Version.HTTP_2).GET().build(); + CompletableFuture> cf = + client.sendAsync(hreq, HttpResponse.BodyHandlers.ofString(UTF_8), pph); + HttpResponse resp = cf.join(); + + // Verify results + verify(resp); + } + + @Test + public void testSendHeadersOnPushPromiseStream() throws Exception { + // This test server sends a push promise that should be followed by a continuation but + // incorrectly sends on Response Headers while the client awaits the continuation. + Http2TestServer faultyServer = new Http2TestServer(false, 0); + faultyServer.addHandler(new ServerPushHandler(), "/"); + faultyServer.setExchangeSupplier(Http2PushPromiseHeadersExchangeImpl::new); + System.err.println("PushPromiseContinuation: FaultyServer listening on port " + faultyServer.getAddress().getPort()); + faultyServer.start(); + + int faultyPort = faultyServer.getAddress().getPort(); + URI faultyUri = new URI("http://localhost:" + faultyPort + "/"); + + HttpClient client = HttpClient.newHttpClient(); + // Server is making a request to an incorrect URI + HttpRequest hreq = HttpRequest.newBuilder(faultyUri).version(HttpClient.Version.HTTP_2).GET().build(); + CompletableFuture> cf = + client.sendAsync(hreq, HttpResponse.BodyHandlers.ofString(UTF_8), pph); + + CompletionException t = expectThrows(CompletionException.class, () -> cf.join()); + assertEquals(t.getCause().getClass(), ProtocolException.class, + "Expected a ProtocolException but got " + t.getCause()); + System.err.println("Client received the following expected exception: " + t.getCause()); + faultyServer.stop(); + } + + private void verify(HttpResponse resp) { + assertEquals(resp.statusCode(), 200); + assertEquals(resp.body(), mainResponseBody); + if (pushPromiseMap.size() > 1) { + System.err.println(pushPromiseMap.entrySet()); + throw new TestException("Results map size is greater than 1"); + } else { + // This will only iterate once + for (HttpRequest r : pushPromiseMap.keySet()) { + HttpResponse serverPushResp = pushPromiseMap.get(r).join(); + // Received headers should be the same as the combined PushPromise + // frame headers combined with the Continuation frame headers + assertEquals(testHeaders, r.headers()); + // Check status code and push promise body are as expected + assertEquals(serverPushResp.statusCode(), 200); + assertEquals(serverPushResp.body(), mainPromiseBody); + } + } + } + + static class Http2PushPromiseHeadersExchangeImpl extends Http2TestExchangeImpl { + + Http2PushPromiseHeadersExchangeImpl(int streamid, String method, HttpHeaders reqheaders, + HttpHeadersBuilder rspheadersBuilder, URI uri, InputStream is, + SSLSession sslSession, BodyOutputStream os, + Http2TestServerConnection conn, boolean pushAllowed) { + super(streamid, method, reqheaders, rspheadersBuilder, uri, is, sslSession, os, conn, pushAllowed); + } + + + @Override + public void serverPush(URI uri, HttpHeaders headers, InputStream content) { + HttpHeadersBuilder headersBuilder = new HttpHeadersBuilder(); + headersBuilder.setHeader(":method", "GET"); + headersBuilder.setHeader(":scheme", uri.getScheme()); + headersBuilder.setHeader(":authority", uri.getAuthority()); + headersBuilder.setHeader(":path", uri.getPath()); + for (Map.Entry> entry : headers.map().entrySet()) { + for (String value : entry.getValue()) + headersBuilder.addHeader(entry.getKey(), value); + } + HttpHeaders combinedHeaders = headersBuilder.build(); + OutgoingPushPromise pp = new OutgoingPushPromise(streamid, uri, combinedHeaders, content); + // Indicates to the client that a continuation should be expected + pp.setFlag(0x0); + try { + conn.outputQ.put(pp); + // writeLoop will spin up thread to read the InputStream + } catch (IOException ex) { + System.err.println("TestServer: pushPromise exception: " + ex); + } + } + } + + static class Http2PushPromiseContinuationExchangeImpl extends Http2TestExchangeImpl { + + HttpHeadersBuilder pushPromiseHeadersBuilder; + List cfs; + + Http2PushPromiseContinuationExchangeImpl(int streamid, String method, HttpHeaders reqheaders, + HttpHeadersBuilder rspheadersBuilder, URI uri, InputStream is, + SSLSession sslSession, BodyOutputStream os, + Http2TestServerConnection conn, boolean pushAllowed) { + super(streamid, method, reqheaders, rspheadersBuilder, uri, is, sslSession, os, conn, pushAllowed); + } + + private void setPushHeaders(String name, String value) { + pushPromiseHeadersBuilder.setHeader(name, value); + testHeadersBuilder.setHeader(name, value); + } + + private void assembleContinuations() { + for (int i = 0; i < continuationCount; i++) { + HttpHeadersBuilder builder = new HttpHeadersBuilder(); + for (int j = 0; j < 10; j++) { + String name = "x-cont-" + i + "-" + j; + builder.setHeader(name, "data_" + j); + testHeadersBuilder.setHeader(name, "data_" + j); + } + + ContinuationFrame cf = new ContinuationFrame(streamid, 0x0, conn.encodeHeaders(builder.build())); + // If this is the last Continuation Frame, set the END_HEADERS flag. + if (i >= continuationCount - 1) { + cf.setFlag(HeaderFrame.END_HEADERS); + } + cfs.add(cf); + } + } + + @Override + public void serverPush(URI uri, HttpHeaders headers, InputStream content) { + pushPromiseHeadersBuilder = new HttpHeadersBuilder(); + testHeadersBuilder = new HttpHeadersBuilder(); + cfs = new ArrayList<>(); + + setPushHeaders(":method", "GET"); + setPushHeaders(":scheme", uri.getScheme()); + setPushHeaders(":authority", uri.getAuthority()); + setPushHeaders(":path", uri.getPath()); + for (Map.Entry> entry : headers.map().entrySet()) { + for (String value : entry.getValue()) { + setPushHeaders(entry.getKey(), value); + } + } + + for (int i = 0; i < 10; i++) { + setPushHeaders("x-push-header-" + i, "data_" + i); + } + + // Create the Continuation Frame/s, done before Push Promise Frame for test purposes + // as testHeaders contains all headers used in all frames + assembleContinuations(); + + HttpHeaders pushPromiseHeaders = pushPromiseHeadersBuilder.build(); + testHeaders = testHeadersBuilder.build(); + // Create the Push Promise Frame + OutgoingPushPromise pp = new OutgoingPushPromise(streamid, uri, pushPromiseHeaders, content, cfs); + + // Indicates to the client that a continuation should be expected + pp.setFlag(0x0); + + try { + // Schedule push promise and continuation for sending + conn.outputQ.put(pp); + System.err.println("Server: Scheduled a Push Promise to Send"); + } catch (IOException ex) { + System.err.println("Server: pushPromise exception: " + ex); + } + } + } + + static class ServerPushHandler implements Http2Handler { + + public void handle(Http2TestExchange exchange) throws IOException { + System.err.println("Server: handle " + exchange); + try (InputStream is = exchange.getRequestBody()) { + is.readAllBytes(); + } + + if (exchange.serverPushAllowed()) { + pushPromise(exchange); + } + + // response data for the main response + try (OutputStream os = exchange.getResponseBody()) { + byte[] bytes = mainResponseBody.getBytes(UTF_8); + exchange.sendResponseHeaders(200, bytes.length); + os.write(bytes); + } + } + + static final BiPredicate ACCEPT_ALL = (x, y) -> true; + + + private void pushPromise(Http2TestExchange exchange) throws IOException { + URI requestURI = exchange.getRequestURI(); + URI uri = requestURI.resolve("/promise"); + InputStream is = new ByteArrayInputStream(mainPromiseBody.getBytes(UTF_8)); + Map> map = new HashMap<>(); + map.put("x-promise", List.of("promise-header")); + HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL); + exchange.serverPush(uri, headers, is); + System.err.println("Server: Push Promise complete"); + } + } +} diff --git a/test/jdk/java/net/httpclient/http2/TrailingHeadersTest.java b/test/jdk/java/net/httpclient/http2/TrailingHeadersTest.java new file mode 100644 index 00000000000..b8d766bb2ca --- /dev/null +++ b/test/jdk/java/net/httpclient/http2/TrailingHeadersTest.java @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2023, 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 Trailing headers should be ignored by the client when using HTTP/2 + * and not affect the rest of the exchange. + * @bug 8296410 + * @library server + * @build Http2TestServer + * @modules java.base/sun.net.www.http + * java.net.http/jdk.internal.net.http.common + * java.net.http/jdk.internal.net.http.frame + * java.net.http/jdk.internal.net.http.hpack + * @run testng/othervm -Djdk.httpclient.HttpClient.log=all TrailingHeadersTest + */ + +import jdk.internal.net.http.common.HttpHeadersBuilder; +import jdk.internal.net.http.frame.DataFrame; +import jdk.internal.net.http.frame.HeaderFrame; +import jdk.internal.net.http.frame.HeadersFrame; +import org.testng.TestException; +import org.testng.annotations.AfterTest; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.BeforeTest; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import javax.net.ssl.SSLSession; +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpHeaders; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.net.http.HttpResponse.BodyHandlers; +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.Executors; +import java.util.function.BiPredicate; + +import static java.net.http.HttpClient.Version.HTTP_2; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.testng.Assert.assertEquals; + +public class TrailingHeadersTest { + + Http2TestServer http2TestServer; + URI trailingURI, trailng1xxURI, trailingPushPromiseURI, warmupURI; + static PrintStream testLog = System.err; + + // Set up simple client-side push promise handler + ConcurrentMap>> pushPromiseMap = new ConcurrentHashMap<>(); + + @BeforeMethod + public void beforeMethod() { + pushPromiseMap = new ConcurrentHashMap<>(); + } + + @BeforeTest + public void setup() throws Exception { + Properties props = new Properties(); + // For triggering trailing headers to send after Push Promise Response headers are sent + props.setProperty("sendTrailingHeadersAfterPushPromise", "1"); + + http2TestServer = new Http2TestServer("Test_Server", + false, + 0, + null, + 0, + props, + null); + http2TestServer.setExchangeSupplier(TrailingHeadersExchange::new); + http2TestServer.addHandler(new ResponseTrailersHandler(), "/ResponseTrailingHeaders"); + http2TestServer.addHandler(new InformationalTrailersHandler(), "/InfoRespTrailingHeaders"); + http2TestServer.addHandler(new PushPromiseTrailersHandler(), "/PushPromiseTrailingHeaders"); + http2TestServer.addHandler(new WarmupHandler(), "/WarmupHandler"); + + http2TestServer.start(); + + trailingURI = URI.create("http://" + http2TestServer.serverAuthority() + "/ResponseTrailingHeaders"); + trailng1xxURI = URI.create("http://" + http2TestServer.serverAuthority() + "/InfoRespTrailingHeaders"); + trailingPushPromiseURI = URI.create("http://" + http2TestServer.serverAuthority() + "/PushPromiseTrailingHeaders"); + + // Used to ensure HTTP/2 upgrade takes place + warmupURI = URI.create("http://" + http2TestServer.serverAuthority() + "/WarmupHandler"); + } + + @AfterTest + public void teardown() { + http2TestServer.stop(); + } + + @Test(dataProvider = "httpRequests") + public void testTrailingHeaders(String description, HttpRequest hRequest, HttpResponse.PushPromiseHandler pph) { + testLog.println("testTrailingHeaders(): " + description); + HttpClient httpClient = HttpClient.newBuilder().build(); + performWarmupRequest(httpClient); + CompletableFuture> cf = httpClient.sendAsync(hRequest, BodyHandlers.ofString(UTF_8), pph); + + testLog.println("testTrailingHeaders(): Performing request: " + hRequest); + HttpResponse resp = cf.join(); + + assertEquals(resp.statusCode(), 200, "Status code of response should be 200"); + + // Verify Push Promise was successful if necessary + if (pph != null) + verifyPushPromise(); + + testLog.println("testTrailingHeaders(): Request successfully completed"); + } + + private void verifyPushPromise() { + assertEquals(pushPromiseMap.size(), 1, "Push Promise should not be greater than 1"); + // This will only iterate once + for (HttpRequest r : pushPromiseMap.keySet()) { + CompletableFuture> serverPushResp = pushPromiseMap.get(r); + // Get the push promise HttpResponse result if present + HttpResponse resp = serverPushResp.join(); + assertEquals(resp.body(), "Sample_Push_Data", "Unexpected Push Promise response body"); + assertEquals(resp.statusCode(), 200, "Status code of Push Promise response should be 200"); + } + } + + private void performWarmupRequest(HttpClient httpClient) { + HttpRequest warmupReq = HttpRequest.newBuilder(warmupURI).version(HTTP_2) + .GET() + .build(); + httpClient.sendAsync(warmupReq, BodyHandlers.discarding()).join(); + } + + @DataProvider(name = "httpRequests") + public Object[][] uris() { + HttpResponse.PushPromiseHandler pph = (initial, pushRequest, acceptor) -> { + HttpResponse.BodyHandler s = HttpResponse.BodyHandlers.ofString(UTF_8); + pushPromiseMap.put(pushRequest, acceptor.apply(s)); + }; + + HttpRequest httpGetTrailing = HttpRequest.newBuilder(trailingURI).version(HTTP_2) + .GET() + .build(); + + HttpRequest httpPost1xxTrailing = HttpRequest.newBuilder(trailng1xxURI).version(HTTP_2) + .POST(HttpRequest.BodyPublishers.ofString("Test Post")) + .expectContinue(true) + .build(); + + HttpRequest httpGetPushPromiseTrailing = HttpRequest.newBuilder(trailingPushPromiseURI).version(HTTP_2) + .GET() + .build(); + + return new Object[][] { + { "Test GET with Trailing Headers", httpGetTrailing, null }, + { "Test POST with 1xx response & Trailing Headers", httpPost1xxTrailing, null }, + { "Test Push Promise with Trailing Headers", httpGetPushPromiseTrailing, pph } + }; + } + + static class TrailingHeadersExchange extends Http2TestExchangeImpl { + + byte[] resp = "Sample_Data".getBytes(StandardCharsets.UTF_8); + + + TrailingHeadersExchange(int streamid, String method, HttpHeaders reqheaders, HttpHeadersBuilder rspheadersBuilder, + URI uri, InputStream is, SSLSession sslSession, BodyOutputStream os, + Http2TestServerConnection conn, boolean pushAllowed) { + super(streamid, method, reqheaders, rspheadersBuilder, uri, is, sslSession, os, conn, pushAllowed); + } + + public void sendResponseThenTrailers() throws IOException { + /* + HttpHeadersBuilder hb = this.conn.createNewHeadersBuilder(); + hb.setHeader("x-sample", "val"); + HeaderFrame headerFrame = new HeadersFrame(this.streamid, 0, this.conn.encodeHeaders(hb.build())); + */ + // TODO: see if there is a safe way to encode headers without interrupting connection thread + HeaderFrame headerFrame = new HeadersFrame(this.streamid, 0, List.of()); + headerFrame.setFlag(HeaderFrame.END_HEADERS); + headerFrame.setFlag(HeaderFrame.END_STREAM); + + this.sendResponseHeaders(200, resp.length); + DataFrame dataFrame = new DataFrame(this.streamid, 0, ByteBuffer.wrap(resp)); + this.conn.addToOutputQ(dataFrame); + this.conn.addToOutputQ(headerFrame); + } + + @Override + public void serverPush(URI uri, HttpHeaders headers, InputStream content) { + HttpHeadersBuilder headersBuilder = new HttpHeadersBuilder(); + headersBuilder.setHeader(":method", "GET"); + headersBuilder.setHeader(":scheme", uri.getScheme()); + headersBuilder.setHeader(":authority", uri.getAuthority()); + headersBuilder.setHeader(":path", uri.getPath()); + for (Map.Entry> entry : headers.map().entrySet()) { + for (String value : entry.getValue()) + headersBuilder.addHeader(entry.getKey(), value); + } + HttpHeaders combinedHeaders = headersBuilder.build(); + OutgoingPushPromise pp = new OutgoingPushPromise(streamid, uri, combinedHeaders, content); + pp.setFlag(HeaderFrame.END_HEADERS); + + try { + this.conn.addToOutputQ(pp); + } catch (IOException ex) { + testLog.println("serverPush(): pushPromise exception: " + ex); + } + } + } + + static class WarmupHandler implements Http2Handler { + + @Override + public void handle(Http2TestExchange exchange) throws IOException { + exchange.sendResponseHeaders(200, 0); + } + } + + static class ResponseTrailersHandler implements Http2Handler { + + @Override + public void handle(Http2TestExchange exchange) throws IOException { + if (exchange.getProtocol().equals("HTTP/2")) { + if (exchange instanceof TrailingHeadersExchange) { + TrailingHeadersExchange trailingHeadersExchange = (TrailingHeadersExchange)exchange; + trailingHeadersExchange.sendResponseThenTrailers(); + } + } else { + testLog.println("ResponseTrailersHandler: Incorrect protocol version"); + exchange.sendResponseHeaders(400, 0); + } + } + } + + static class InformationalTrailersHandler implements Http2Handler { + + @Override + public void handle(Http2TestExchange exchange) throws IOException { + if (exchange.getProtocol().equals("HTTP/2")) { + if (exchange instanceof TrailingHeadersExchange) { + TrailingHeadersExchange trailingHeadersExchange = (TrailingHeadersExchange)exchange; + testLog.println(this.getClass().getCanonicalName() + ": Sending status 100"); + trailingHeadersExchange.sendResponseHeaders(100, 0); + + try (InputStream is = exchange.getRequestBody()) { + is.readAllBytes(); + trailingHeadersExchange.sendResponseThenTrailers(); + } + } + } else { + testLog.println("InformationalTrailersHandler: Incorrect protocol version"); + exchange.sendResponseHeaders(400, 0); + } + } + } + + static class PushPromiseTrailersHandler implements Http2Handler { + + @Override + public void handle(Http2TestExchange exchange) throws IOException { + if (exchange.getProtocol().equals("HTTP/2")) { + if (exchange instanceof TrailingHeadersExchange) { + TrailingHeadersExchange trailingHeadersExchange = (TrailingHeadersExchange)exchange; + try (InputStream is = exchange.getRequestBody()) { + is.readAllBytes(); + } + + if (exchange.serverPushAllowed()) { + pushPromise(trailingHeadersExchange); + } + + try (OutputStream os = trailingHeadersExchange.getResponseBody()) { + byte[] bytes = "Sample_Data".getBytes(UTF_8); + trailingHeadersExchange.sendResponseHeaders(200, bytes.length); + os.write(bytes); + } + } + } + } + + static final BiPredicate ACCEPT_ALL = (x, y) -> true; + + private void pushPromise(Http2TestExchange exchange) { + URI requestURI = exchange.getRequestURI(); + URI uri = requestURI.resolve("/promise"); + InputStream is = new ByteArrayInputStream("Sample_Push_Data".getBytes(UTF_8)); + Map> map = new HashMap<>(); + map.put("x-promise", List.of("promise-header")); + HttpHeaders headers = HttpHeaders.of(map, ACCEPT_ALL); + exchange.serverPush(uri, headers, is); + testLog.println("PushPromiseTrailersHandler: Push Promise complete"); + } + } +} \ No newline at end of file diff --git a/test/jdk/java/net/httpclient/http2/server/BodyOutputStream.java b/test/jdk/java/net/httpclient/http2/server/BodyOutputStream.java index 008d9bdffc1..d08495e709d 100644 --- a/test/jdk/java/net/httpclient/http2/server/BodyOutputStream.java +++ b/test/jdk/java/net/httpclient/http2/server/BodyOutputStream.java @@ -128,10 +128,14 @@ public void close() { closed = true; } try { - send(EMPTY_BARRAY, 0, 0, DataFrame.END_STREAM); + sendEndStream(); } catch (IOException ex) { System.err.println("TestServer: OutputStream.close exception: " + ex); ex.printStackTrace(); } } + + protected void sendEndStream() throws IOException { + send(EMPTY_BARRAY, 0, 0, DataFrame.END_STREAM); + } } diff --git a/test/jdk/java/net/httpclient/http2/server/HpackTestEncoder.java b/test/jdk/java/net/httpclient/http2/server/HpackTestEncoder.java new file mode 100644 index 00000000000..04f549d7194 --- /dev/null +++ b/test/jdk/java/net/httpclient/http2/server/HpackTestEncoder.java @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2015, 2023, 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.function.*; + +import jdk.internal.net.http.hpack.Encoder; + +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; +import static jdk.internal.net.http.hpack.HPACK.Logger.Level.EXTRA; +import static jdk.internal.net.http.hpack.HPACK.Logger.Level.NORMAL; + +public class HpackTestEncoder extends Encoder { + + public HpackTestEncoder(int maxCapacity) { + super(maxCapacity); + } + + /** + * Sets up the given header {@code (name, value)} with possibly sensitive + * value. + * + *

    If the {@code value} is sensitive (think security, secrecy, etc.) + * this encoder will compress it using a special representation + * (see 6.2.3. Literal Header Field Never Indexed). + * + *

    Fixates {@code name} and {@code value} for the duration of encoding. + * + * @param name + * the name + * @param value + * the value + * @param sensitive + * whether or not the value is sensitive + * + * @throws NullPointerException + * if any of the arguments are {@code null} + * @throws IllegalStateException + * if the encoder hasn't fully encoded the previous header, or + * hasn't yet started to encode it + * @see #header(CharSequence, CharSequence) + * @see DecodingCallback#onDecoded(CharSequence, CharSequence, boolean) + */ + public void header(CharSequence name, + CharSequence value, + boolean sensitive) throws IllegalStateException { + if (sensitive || getMaxCapacity() == 0) { + super.header(name, value, true); + } else { + header(name, value, false, (n,v) -> false); + } + } + /** + * Sets up the given header {@code (name, value)} with possibly sensitive + * value. + * + *

    If the {@code value} is sensitive (think security, secrecy, etc.) + * this encoder will compress it using a special representation + * (see 6.2.3. Literal Header Field Never Indexed). + * + *

    Fixates {@code name} and {@code value} for the duration of encoding. + * + * @param name + * the name + * @param value + * the value + * @param insertionPolicy + * a bipredicate to indicate whether a name value pair + * should be added to the dynamic table + * + * @throws NullPointerException + * if any of the arguments are {@code null} + * @throws IllegalStateException + * if the encoder hasn't fully encoded the previous header, or + * hasn't yet started to encode it + * @see #header(CharSequence, CharSequence) + * @see DecodingCallback#onDecoded(CharSequence, CharSequence, boolean) + */ + public void header(CharSequence name, + CharSequence value, + BiPredicate insertionPolicy) + throws IllegalStateException { + header(name, value, false, insertionPolicy); + } + + /** + * Sets up the given header {@code (name, value)} with possibly sensitive + * value. + * + *

    If the {@code value} is sensitive (think security, secrecy, etc.) + * this encoder will compress it using a special representation + * (see + * 6.2.3. Literal Header Field Never Indexed). + * + *

    Fixates {@code name} and {@code value} for the duration of encoding. + * + * @param name + * the name + * @param value + * the value + * @param sensitive + * whether or not the value is sensitive + * @param insertionPolicy + * a bipredicate to indicate whether a name value pair + * should be added to the dynamic table + * + * @throws NullPointerException + * if any of the arguments are {@code null} + * @throws IllegalStateException + * if the encoder hasn't fully encoded the previous header, or + * hasn't yet started to encode it + * @see #header(CharSequence, CharSequence) + * @see DecodingCallback#onDecoded(CharSequence, CharSequence, boolean) + */ + public void header(CharSequence name, + CharSequence value, + boolean sensitive, + BiPredicate insertionPolicy) + throws IllegalStateException { + if (sensitive == true || getMaxCapacity() == 0 || !insertionPolicy.test(name, value)) { + super.header(name, value, sensitive); + return; + } + var logger = logger(); + // Arguably a good balance between complexity of implementation and + // efficiency of encoding + requireNonNull(name, "name"); + requireNonNull(value, "value"); + var t = getHeaderTable(); + int index = tableIndexOf(name, value); + if (logger.isLoggable(NORMAL)) { + logger.log(NORMAL, () -> format("encoding with indexing ('%s', '%s'): index:%s", + name, value, index)); + } + if (index > 0) { + indexed(index); + } else { + boolean huffmanValue = isHuffmanBetterFor(value); + if (index < 0) { + literalWithIndexing(-index, value, huffmanValue); + } else { + boolean huffmanName = isHuffmanBetterFor(name); + literalWithIndexing(name, huffmanName, value, huffmanValue); + } + } + } + + protected int calculateCapacity(int maxCapacity) { + return maxCapacity; + } + +} diff --git a/test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java b/test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java index 30aad46b178..3f068440b46 100644 --- a/test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java +++ b/test/jdk/java/net/httpclient/http2/server/Http2TestExchange.java @@ -27,9 +27,12 @@ import java.net.URI; import java.net.InetSocketAddress; import java.net.http.HttpHeaders; +import java.util.List; import java.util.concurrent.CompletableFuture; +import java.util.function.BiPredicate; import javax.net.ssl.SSLSession; import jdk.internal.net.http.common.HttpHeadersBuilder; +import jdk.internal.net.http.frame.Http2Frame; public interface Http2TestExchange { @@ -51,6 +54,12 @@ public interface Http2TestExchange { void sendResponseHeaders(int rCode, long responseLength) throws IOException; + default void sendResponseHeaders(int rCode, long responseLength, + BiPredicate insertionPolicy) + throws IOException { + sendResponseHeaders(rCode, responseLength); + } + InetSocketAddress getRemoteAddress(); int getResponseCode(); @@ -63,6 +72,10 @@ public interface Http2TestExchange { void serverPush(URI uri, HttpHeaders headers, InputStream content); + default void sendFrames(List frames) throws IOException { + throw new UnsupportedOperationException("not implemented"); + } + /** * Send a PING on this exchanges connection, and completes the returned CF * with the number of milliseconds it took to get a valid response. diff --git a/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeImpl.java b/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeImpl.java index 7bb8ad57e45..f4c6bdbf648 100644 --- a/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeImpl.java +++ b/test/jdk/java/net/httpclient/http2/server/Http2TestExchangeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ -21,19 +21,22 @@ * questions. */ +import jdk.internal.net.http.common.HttpHeadersBuilder; +import jdk.internal.net.http.frame.HeaderFrame; +import jdk.internal.net.http.frame.HeadersFrame; +import jdk.internal.net.http.frame.Http2Frame; + +import javax.net.ssl.SSLSession; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.IOException; -import java.net.URI; import java.net.InetSocketAddress; +import java.net.URI; import java.net.http.HttpHeaders; import java.util.List; import java.util.Map; import java.util.concurrent.CompletableFuture; -import javax.net.ssl.SSLSession; -import jdk.internal.net.http.common.HttpHeadersBuilder; -import jdk.internal.net.http.frame.HeaderFrame; -import jdk.internal.net.http.frame.HeadersFrame; +import java.util.function.BiPredicate; public class Http2TestExchangeImpl implements Http2TestExchange { @@ -127,8 +130,13 @@ public OutputStream getResponseBody() { return os; } - @Override public void sendResponseHeaders(int rCode, long responseLength) throws IOException { + sendResponseHeaders(rCode, responseLength, (n,v) -> false); + } + @Override + public void sendResponseHeaders(int rCode, long responseLength, + BiPredicate insertionPolicy) + throws IOException { this.responseLength = responseLength; if (responseLength !=0 && rCode != 204 && !isHeadRequest()) { long clen = responseLength > 0 ? responseLength : 0; @@ -139,7 +147,7 @@ public void sendResponseHeaders(int rCode, long responseLength) throws IOExcepti HttpHeaders headers = rspheadersBuilder.build(); Http2TestServerConnection.ResponseHeaders response - = new Http2TestServerConnection.ResponseHeaders(headers); + = new Http2TestServerConnection.ResponseHeaders(headers, insertionPolicy); response.streamid(streamid); response.setFlag(HeaderFrame.END_HEADERS); @@ -153,6 +161,11 @@ public void sendResponseHeaders(int rCode, long responseLength) throws IOExcepti System.err.println("Sent response headers " + rCode); } + @Override + public void sendFrames(List frames) throws IOException { + conn.sendFrames(frames); + } + @Override public InetSocketAddress getRemoteAddress() { return (InetSocketAddress) conn.socket.getRemoteSocketAddress(); @@ -191,6 +204,7 @@ public void serverPush(URI uri, HttpHeaders headers, InputStream content) { } HttpHeaders combinedHeaders = headersBuilder.build(); OutgoingPushPromise pp = new OutgoingPushPromise(streamid, uri, combinedHeaders, content); + pp.setFlag(HeaderFrame.END_HEADERS); try { conn.outputQ.put(pp); diff --git a/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java b/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java index 33e5ade4f83..e4388901070 100644 --- a/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java +++ b/test/jdk/java/net/httpclient/http2/server/Http2TestServer.java @@ -171,7 +171,7 @@ public Http2TestServer(String serverName, this.secure = secure; this.exec = exec == null ? getDefaultExecutor() : exec; this.handlers = Collections.synchronizedMap(new HashMap<>()); - this.properties = properties; + this.properties = properties == null ? new Properties() : properties; this.connections = new HashMap<>(); } diff --git a/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java b/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java index 3c3b9ea985b..7e45743934d 100644 --- a/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java +++ b/test/jdk/java/net/httpclient/http2/server/Http2TestServerConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ -21,34 +21,70 @@ * questions. */ +import jdk.internal.net.http.common.HttpHeadersBuilder; +import jdk.internal.net.http.common.Log; +import jdk.internal.net.http.frame.ContinuationFrame; +import jdk.internal.net.http.frame.DataFrame; +import jdk.internal.net.http.frame.ErrorFrame; +import jdk.internal.net.http.frame.FramesDecoder; +import jdk.internal.net.http.frame.FramesEncoder; +import jdk.internal.net.http.frame.GoAwayFrame; +import jdk.internal.net.http.frame.HeaderFrame; +import jdk.internal.net.http.frame.HeadersFrame; +import jdk.internal.net.http.frame.Http2Frame; +import jdk.internal.net.http.frame.PingFrame; +import jdk.internal.net.http.frame.PushPromiseFrame; +import jdk.internal.net.http.frame.ResetFrame; +import jdk.internal.net.http.frame.SettingsFrame; +import jdk.internal.net.http.frame.WindowUpdateFrame; +import jdk.internal.net.http.hpack.Decoder; +import jdk.internal.net.http.hpack.DecodingCallback; +import jdk.internal.net.http.hpack.Encoder; +import sun.net.www.http.ChunkedInputStream; +import sun.net.www.http.HttpClient; + +import javax.net.ssl.SNIHostName; +import javax.net.ssl.SNIMatcher; +import javax.net.ssl.SNIServerName; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.StandardConstants; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.Closeable; import java.io.IOException; -import java.io.UncheckedIOException; import java.io.InputStream; import java.io.OutputStream; +import java.io.UncheckedIOException; +import java.net.InetAddress; import java.net.Socket; import java.net.URI; -import java.net.InetAddress; -import javax.net.ssl.*; import java.net.URISyntaxException; import java.net.http.HttpHeaders; import java.nio.ByteBuffer; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.Properties; +import java.util.Random; import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.locks.ReentrantLock; +import java.util.function.BiPredicate; import java.util.function.Consumer; -import jdk.internal.net.http.common.HttpHeadersBuilder; -import jdk.internal.net.http.frame.*; -import jdk.internal.net.http.hpack.Decoder; -import jdk.internal.net.http.hpack.DecodingCallback; -import jdk.internal.net.http.hpack.Encoder; -import sun.net.www.http.ChunkedInputStream; -import sun.net.www.http.HttpClient; + import static java.nio.charset.StandardCharsets.ISO_8859_1; import static java.nio.charset.StandardCharsets.UTF_8; +import static jdk.internal.net.http.frame.SettingsFrame.DEFAULT_MAX_FRAME_SIZE; import static jdk.internal.net.http.frame.SettingsFrame.HEADER_TABLE_SIZE; /** @@ -67,7 +103,7 @@ public class Http2TestServerConnection { final Http2TestExchangeSupplier exchangeSupplier; final InputStream is; final OutputStream os; - volatile Encoder hpackOut; + volatile HpackTestEncoder hpackOut; volatile Decoder hpackIn; volatile SettingsFrame clientSettings; final SettingsFrame serverSettings; @@ -215,6 +251,10 @@ private PingRequest getNextRequest() { return pings.poll(); } + public void addToOutputQ(final Http2Frame frame) throws IOException { + outputQ.put(frame); + } + /** * Handles incoming Ping, which could be an ack * or a client originated Ping @@ -356,7 +396,9 @@ private SettingsFrame getSettingsFromString(String s) throws IOException { } public int getMaxFrameSize() { - return clientSettings.getParameter(SettingsFrame.MAX_FRAME_SIZE); + var max = clientSettings.getParameter(SettingsFrame.MAX_FRAME_SIZE); + if (max <= 0) max = DEFAULT_MAX_FRAME_SIZE; + return max; } /** Sends a pre-canned HTTP/1.1 response. */ @@ -417,7 +459,7 @@ void run() throws Exception { //System.out.println("ServerSettings: " + serverSettings); //System.out.println("ClientSettings: " + clientSettings); - hpackOut = new Encoder(serverSettings.getParameter(HEADER_TABLE_SIZE)); + hpackOut = new HpackTestEncoder(serverSettings.getParameter(HEADER_TABLE_SIZE)); hpackIn = new Decoder(clientSettings.getParameter(HEADER_TABLE_SIZE)); if (!secure) { @@ -703,6 +745,14 @@ headers, rspheadersBuilder, uri, bis, getSSLSession(), } } + public void sendFrames(List frames) throws IOException { + synchronized (outputQ) { + for (var frame : frames) { + outputQ.put(frame); + } + } + } + protected HttpHeadersBuilder createNewHeadersBuilder() { return new HttpHeadersBuilder(); } @@ -813,26 +863,38 @@ static boolean isServerStreamId(int streamid) { return (streamid & 0x01) == 0x00; } + final ReentrantLock headersLock = new ReentrantLock(); + /** Encodes an group of headers, without any ordering guarantees. */ List encodeHeaders(HttpHeaders headers) { + return encodeHeaders(headers, (n,v) -> false); + } + + public List encodeHeaders(HttpHeaders headers, + BiPredicate insertionPolicy) { List buffers = new LinkedList<>(); ByteBuffer buf = getBuffer(); boolean encoded; - for (Map.Entry> entry : headers.map().entrySet()) { - List values = entry.getValue(); - String key = entry.getKey().toLowerCase(); - for (String value : values) { - do { - hpackOut.header(key, value); - encoded = hpackOut.encode(buf); - if (!encoded) { - buf.flip(); - buffers.add(buf); - buf = getBuffer(); - } - } while (!encoded); + headersLock.lock(); + try { + for (Map.Entry> entry : headers.map().entrySet()) { + List values = entry.getValue(); + String key = entry.getKey().toLowerCase(); + for (String value : values) { + hpackOut.header(key, value, insertionPolicy); + do { + encoded = hpackOut.encode(buf); + if (!encoded && !buf.hasRemaining()) { + buf.flip(); + buffers.add(buf); + buf = getBuffer(); + } + } while (!encoded); + } } + } finally { + headersLock.unlock(); } buf.flip(); buffers.add(buf); @@ -845,18 +907,23 @@ List encodeHeadersOrdered(List> headers) { ByteBuffer buf = getBuffer(); boolean encoded; - for (Map.Entry entry : headers) { - String value = entry.getValue(); - String key = entry.getKey().toLowerCase(); - do { + headersLock.lock(); + try { + for (Map.Entry entry : headers) { + String value = entry.getValue(); + String key = entry.getKey().toLowerCase(); hpackOut.header(key, value); - encoded = hpackOut.encode(buf); - if (!encoded) { - buf.flip(); - buffers.add(buf); - buf = getBuffer(); - } - } while (!encoded); + do { + encoded = hpackOut.encode(buf); + if (!encoded && !buf.hasRemaining()) { + buf.flip(); + buffers.add(buf); + buf = getBuffer(); + } + } while (!encoded); + } + } finally { + headersLock.unlock(); } buf.flip(); buffers.add(buf); @@ -885,8 +952,49 @@ void writeLoop() { } if (frame instanceof ResponseHeaders) { ResponseHeaders rh = (ResponseHeaders)frame; - HeadersFrame hf = new HeadersFrame(rh.streamid(), rh.getFlags(), encodeHeaders(rh.headers)); - writeFrame(hf); + var buffers = encodeHeaders(rh.headers, rh.insertionPolicy); + int maxFrameSize = Math.min(rh.getMaxFrameSize(), getMaxFrameSize() - 64); + int next = 0; + int cont = 0; + do { + // If the total size of headers exceeds the max frame + // size we need to split the headers into one + // HeadersFrame + N x ContinuationFrames + int remaining = maxFrameSize; + var list = new ArrayList(buffers.size()); + for (; next < buffers.size(); next++) { + var b = buffers.get(next); + var len = b.remaining(); + if (!b.hasRemaining()) continue; + if (len <= remaining) { + remaining -= len; + list.add(b); + } else { + if (next == 0) { + list.add(b.slice().limit(remaining)); + b.position(b.position() + remaining); + remaining = 0; + } + break; + } + } + int flags = rh.getFlags(); + if (next != buffers.size()) { + flags = flags & ~HeadersFrame.END_HEADERS; + } + if (cont > 0) { + flags = flags & ~HeadersFrame.END_STREAM; + } + HeaderFrame hf = cont == 0 + ? new HeadersFrame(rh.streamid(), flags, list) + : new ContinuationFrame(rh.streamid(), flags, list); + if (Log.headers()) { + // avoid too much chatter: log only if Log.headers() is enabled + System.err.println("TestServer writing " + hf); + } + writeFrame(hf); + cont++; + } while (next < buffers.size()); } else if (frame instanceof OutgoingPushPromise) { handlePush((OutgoingPushPromise)frame); } else @@ -906,7 +1014,7 @@ void writeLoop() { private void handlePush(OutgoingPushPromise op) throws IOException { int promisedStreamid = nextPushStreamId; PushPromiseFrame pp = new PushPromiseFrame(op.parentStream, - HeaderFrame.END_HEADERS, + op.getFlags(), promisedStreamid, encodeHeaders(op.headers), 0); @@ -914,17 +1022,34 @@ private void handlePush(OutgoingPushPromise op) throws IOException { nextPushStreamId += 2; pp.streamid(op.parentStream); writeFrame(pp); + // No need to check for END_HEADERS flag here to allow for tests to simulate bad server side + // behavior i.e Continuation Frames included with END_HEADERS flag set + for (Http2Frame cf : op.getContinuations()) + writeFrame(cf); + final InputStream ii = op.is; final BodyOutputStream oo = new BodyOutputStream( promisedStreamid, clientSettings.getParameter( - SettingsFrame.INITIAL_WINDOW_SIZE), this); + SettingsFrame.INITIAL_WINDOW_SIZE), this) { + + @Override + protected void sendEndStream() throws IOException { + if (properties.getProperty("sendTrailingHeadersAfterPushPromise", "0").equals("1")) { + conn.outputQ.put(getTrailingHeadersFrame(promisedStreamid, List.of())); + } else { + super.sendEndStream(); + } + } + }; + outStreams.put(promisedStreamid, oo); oo.goodToGo(); exec.submit(() -> { try { ResponseHeaders oh = getPushResponse(promisedStreamid); outputQ.put(oh); + ii.transferTo(oo); } catch (Throwable ex) { System.err.printf("TestServer: pushing response error: %s\n", @@ -937,6 +1062,11 @@ private void handlePush(OutgoingPushPromise op) throws IOException { } + private HeadersFrame getTrailingHeadersFrame(int promisedStreamid, List headerBlocks) { + // TODO: see if there is a safe way to encode headers without interrupting connection thread + return new HeadersFrame(promisedStreamid, (HeaderFrame.END_HEADERS | HeaderFrame.END_STREAM), headerBlocks); + } + // returns a minimal response with status 200 // that is the response to the push promise just sent private ResponseHeaders getPushResponse(int streamid) { @@ -1175,11 +1305,29 @@ synchronized void updateConnectionWindow(int amount) { // for the hashmap. static class ResponseHeaders extends Http2Frame { - HttpHeaders headers; + final HttpHeaders headers; + final BiPredicate insertionPolicy; + + final int maxFrameSize; + + public ResponseHeaders(HttpHeaders headers) { + this(headers, (n,v) -> false); + } + public ResponseHeaders(HttpHeaders headers, BiPredicate insertionPolicy) { + this(headers, insertionPolicy, Integer.MAX_VALUE); + } - ResponseHeaders(HttpHeaders headers) { + public ResponseHeaders(HttpHeaders headers, + BiPredicate insertionPolicy, + int maxFrameSize) { super(0, 0); this.headers = headers; + this.insertionPolicy = insertionPolicy; + this.maxFrameSize = maxFrameSize; + } + + public int getMaxFrameSize() { + return maxFrameSize; } } diff --git a/test/jdk/java/net/httpclient/http2/server/OutgoingPushPromise.java b/test/jdk/java/net/httpclient/http2/server/OutgoingPushPromise.java index 7b2124b73da..cd4fca0a817 100644 --- a/test/jdk/java/net/httpclient/http2/server/OutgoingPushPromise.java +++ b/test/jdk/java/net/httpclient/http2/server/OutgoingPushPromise.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,9 @@ import java.io.InputStream; import java.net.URI; import java.net.http.HttpHeaders; +import java.util.List; + +import jdk.internal.net.http.frame.ContinuationFrame; import jdk.internal.net.http.frame.Http2Frame; // will be converted to a PushPromiseFrame in the writeLoop @@ -33,16 +36,29 @@ class OutgoingPushPromise extends Http2Frame { final URI uri; final InputStream is; final int parentStream; // not the pushed streamid + private final List continuations; public OutgoingPushPromise(int parentStream, URI uri, HttpHeaders headers, InputStream is) { + this(parentStream, uri, headers, is, List.of()); + } + + public OutgoingPushPromise(int parentStream, + URI uri, + HttpHeaders headers, + InputStream is, + List continuations) { super(0,0); this.uri = uri; this.headers = headers; this.is = is; this.parentStream = parentStream; + this.continuations = List.copyOf(continuations); } + public List getContinuations() { + return continuations; + } } diff --git a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java index ac251f9ba7d..114110344a4 100644 --- a/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java +++ b/test/jdk/java/net/httpclient/whitebox/java.net.http/jdk/internal/net/http/SSLTubeTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, 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 @@ -85,16 +85,17 @@ private static class SSLLoopbackSubscriber implements FlowTube { ExecutorService exec, CountDownLatch allBytesReceived) throws IOException { SSLServerSocketFactory fac = ctx.getServerSocketFactory(); + InetAddress loopback = InetAddress.getLoopbackAddress(); SSLServerSocket serv = (SSLServerSocket) fac.createServerSocket(); serv.setReuseAddress(false); - serv.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + serv.bind(new InetSocketAddress(loopback, 0)); SSLParameters params = serv.getSSLParameters(); params.setApplicationProtocols(new String[]{"proto2"}); serv.setSSLParameters(params); int serverPort = serv.getLocalPort(); - clientSock = new Socket("localhost", serverPort); + clientSock = new Socket(loopback, serverPort); serverSock = (SSLSocket) serv.accept(); this.buffer = new LinkedBlockingQueue<>(); this.allBytesReceived = allBytesReceived; @@ -107,6 +108,7 @@ private static class SSLLoopbackSubscriber implements FlowTube { } public void start() { + System.out.println("Starting: server listening at: " + serverSock.getLocalSocketAddress()); thread1.start(); thread2.start(); thread3.start(); @@ -144,6 +146,7 @@ private void clientReader() { publisher.submit(List.of(bb)); } } catch (Throwable e) { + System.out.println("clientReader got exception: " + e); e.printStackTrace(); Utils.close(clientSock); } @@ -176,6 +179,7 @@ private void clientWriter() { clientSubscription.request(1); } } catch (Throwable e) { + System.out.println("clientWriter got exception: " + e); e.printStackTrace(); } } @@ -212,6 +216,7 @@ private void serverLoopback() { is.close(); os.close(); serverSock.close(); + System.out.println("serverLoopback exiting normally"); return; } os.write(bb, 0, n); @@ -219,7 +224,10 @@ private void serverLoopback() { loopCount.addAndGet(n); } } catch (Throwable e) { + System.out.println("serverLoopback got exception: " + e); e.printStackTrace(); + } finally { + System.out.println("serverLoopback exiting at count: " + loopCount.get()); } } diff --git a/test/jdk/java/nio/channels/AsyncCloseAndInterrupt.java b/test/jdk/java/nio/channels/AsyncCloseAndInterrupt.java index 31f87137838..6bf46a8aa56 100644 --- a/test/jdk/java/nio/channels/AsyncCloseAndInterrupt.java +++ b/test/jdk/java/nio/channels/AsyncCloseAndInterrupt.java @@ -129,6 +129,7 @@ private static void initFile() throws Exception { return; } fifoFile = new File("x.fifo"); + fifoFile.deleteOnExit(); if (fifoFile.exists()) { if (!fifoFile.delete()) throw new IOException("Cannot delete existing fifo " + fifoFile); diff --git a/test/jdk/java/text/Format/MessageFormat/MaxArgumentIndexTest.java b/test/jdk/java/text/Format/MessageFormat/MaxArgumentIndexTest.java new file mode 100644 index 00000000000..e12dabb6383 --- /dev/null +++ b/test/jdk/java/text/Format/MessageFormat/MaxArgumentIndexTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2024, 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 8331446 + * @summary Enforce the MAX_ARGUMENT_INDEX(10,000) implementation limit for the + * ArgumentIndex element in the MessageFormat pattern syntax. This + * should be checked during construction/applyPattern/readObject and should effectively + * prevent parse/format from being invoked with values over the limit. + * @run junit MaxArgumentIndexTest + */ + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.text.MessageFormat; +import java.util.Locale; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertThrows; + +public class MaxArgumentIndexTest { + + // A MessageFormat pattern that contains an ArgumentIndex value + // which violates this implementation's limit: MAX_ARGUMENT_INDEX(10,000) + // As this check is exclusive, 10,000 will violate the limit + private static final String VIOLATES_MAX_ARGUMENT_INDEX = "{10000}"; + + // Check String constructor enforces the limit + @Test + public void constructorTest() { + assertThrows(IllegalArgumentException.class, + () -> new MessageFormat(VIOLATES_MAX_ARGUMENT_INDEX)); + } + + // Check String, Locale constructor enforces the limit + @ParameterizedTest + @MethodSource + public void constructorWithLocaleTest(Locale locale) { + assertThrows(IllegalArgumentException.class, + () -> new MessageFormat(VIOLATES_MAX_ARGUMENT_INDEX, locale)); + } + + // Provide some basic common locale values + private static Stream constructorWithLocaleTest() { + return Stream.of(null, Locale.US, Locale.ROOT); + } + + // Edge case: Test a locale dependent subformat (with null locale) with a + // violating ArgumentIndex. In this instance, the violating ArgumentIndex + // will be caught and IAE thrown instead of the NPE + @Test + public void localeDependentSubFormatTest() { + assertThrows(IllegalArgumentException.class, + () -> new MessageFormat("{10000,number,short}", null)); + // For reference + assertThrows(NullPointerException.class, + () -> new MessageFormat("{999,number,short}", null)); + } + + // Check that the static format method enforces the limit + @Test + public void staticFormatTest() { + assertThrows(IllegalArgumentException.class, + () -> MessageFormat.format(VIOLATES_MAX_ARGUMENT_INDEX, new Object[]{1})); + } + + // Check that applyPattern(String) enforces the limit + @Test + public void applyPatternTest() { + MessageFormat mf = new MessageFormat(""); + assertThrows(IllegalArgumentException.class, + () -> mf.applyPattern(VIOLATES_MAX_ARGUMENT_INDEX)); + } +} diff --git a/test/jdk/java/text/Format/MessageFormat/SerializationTest.java b/test/jdk/java/text/Format/MessageFormat/SerializationTest.java new file mode 100644 index 00000000000..9191c5caef3 --- /dev/null +++ b/test/jdk/java/text/Format/MessageFormat/SerializationTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2024, 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 8331446 + * @summary Check correctness of deserialization + * @run junit SerializationTest + */ + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.text.MessageFormat; +import java.util.Locale; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class SerializationTest { + + // Ensure basic correctness of serialization round trip + @ParameterizedTest + @MethodSource + public void serializationRoundTrip(MessageFormat expectedMf) + throws IOException, ClassNotFoundException { + byte[] bytes = ser(expectedMf); + MessageFormat actualMf = (MessageFormat) deSer(bytes); + assertEquals(expectedMf, actualMf); + } + + // Various valid MessageFormats + private static Stream serializationRoundTrip() { + return Stream.of( + // basic pattern + new MessageFormat("{0} foo"), + // Multiple arguments + new MessageFormat("{0} {1} foo"), + // duplicate arguments + new MessageFormat("{0} {0} {1} foo"), + // Non-ascending arguments + new MessageFormat("{1} {0} foo"), + // With locale + new MessageFormat("{1} {0} foo", Locale.UK), + // With null locale. (NPE not thrown, if no format defined) + new MessageFormat("{1} {0} foo", null), + // With formats + new MessageFormat("{0,number,short} {0} {1,date,long} foo") + ); + } + + // Utility method to serialize + private static byte[] ser(Object obj) throws IOException { + ByteArrayOutputStream byteArrayOutputStream = new + ByteArrayOutputStream(); + ObjectOutputStream oos = new + ObjectOutputStream(byteArrayOutputStream); + oos.writeObject(obj); + return byteArrayOutputStream.toByteArray(); + } + + // Utility method to deserialize + private static Object deSer(byte[] bytes) throws + IOException, ClassNotFoundException { + ByteArrayInputStream byteArrayInputStream = new + ByteArrayInputStream(bytes); + ObjectInputStream ois = new + ObjectInputStream(byteArrayInputStream); + return ois.readObject(); + } +} diff --git a/test/jdk/java/util/Currency/CheckDataVersion.java b/test/jdk/java/util/Currency/CheckDataVersion.java index ba18677dbbe..303603c5b85 100644 --- a/test/jdk/java/util/Currency/CheckDataVersion.java +++ b/test/jdk/java/util/Currency/CheckDataVersion.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 @@ -38,7 +38,7 @@ import java.util.Currency; class CheckDataVersion { - static final String datafile = "tablea1.txt"; + static final String datafile = "ISO4217-list-one.txt"; static final String FILEVERSIONKEY = "FILEVERSION="; static final String DATAVERSIONKEY = "DATAVERSION="; static String fileVersion; diff --git a/test/jdk/java/util/Currency/CurrencyTest.java b/test/jdk/java/util/Currency/CurrencyTest.java index 380bf3b338a..12540d21f75 100644 --- a/test/jdk/java/util/Currency/CurrencyTest.java +++ b/test/jdk/java/util/Currency/CurrencyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 4290801 4692419 4693631 5101540 5104960 6296410 6336600 6371531 * 6488442 7036905 8008577 8039317 8074350 8074351 8150324 8167143 - * 8264792 + * 8264792 8334653 * @summary Basic tests for Currency class. * @modules java.base/java.util:open * jdk.localedata @@ -60,7 +60,7 @@ public class CurrencyTest { - // 'tablea1.txt' should be up-to-date before testing + // 'ISO4217-list-one.txt' should be up-to-date before testing @Test public void dataVersionTest() { CheckDataVersion.check(); diff --git a/test/jdk/java/util/Currency/tablea1.txt b/test/jdk/java/util/Currency/ISO4217-list-one.txt similarity index 97% rename from test/jdk/java/util/Currency/tablea1.txt rename to test/jdk/java/util/Currency/ISO4217-list-one.txt index 6e85de5e6d2..1912b5cc7db 100644 --- a/test/jdk/java/util/Currency/tablea1.txt +++ b/test/jdk/java/util/Currency/ISO4217-list-one.txt @@ -1,12 +1,12 @@ # # -# Amendments up until ISO 4217 AMENDMENT NUMBER 176 -# (As of 06 December 2023) +# Amendments up until ISO 4217 AMENDMENT NUMBER 177 +# (As of 20 June 2024) # # Version FILEVERSION=3 -DATAVERSION=176 +DATAVERSION=177 # ISO 4217 currency data AF AFN 971 2 @@ -276,7 +276,7 @@ WF XPF 953 0 EH MAD 504 2 YE YER 886 2 ZM ZMW 967 2 -ZW ZWL 932 2 +ZW ZWG 924 2 #XAU XAU 959 #XBA XBA 955 #XBB XBB 956 diff --git a/test/jdk/java/util/Currency/ValidateISO4217.java b/test/jdk/java/util/Currency/ValidateISO4217.java index 9a92e74eb3f..01c225e531c 100644 --- a/test/jdk/java/util/Currency/ValidateISO4217.java +++ b/test/jdk/java/util/Currency/ValidateISO4217.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2024, 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 4691089 4819436 4942982 5104960 6544471 6627549 7066203 7195759 * 8039317 8074350 8074351 8145952 8187946 8193552 8202026 8204269 - * 8208746 8209775 8264792 8274658 8283277 8296239 8321480 + * 8208746 8209775 8264792 8274658 8283277 8296239 8321480 8334653 * @summary Validate ISO 4217 data for Currency class. * @modules java.base/java.util:open * jdk.localedata @@ -60,7 +60,8 @@ /** * This class tests the latest ISO 4217 data and Java's currency data which is - * based on ISO 4217. The golden-data file (ISO 4217 data) 'tablea1.txt' has the following + * based on ISO 4217. The golden-data file, 'ISO4217-list-one.txt', based on the + * "List one: Currency, fund and precious metal codes" has the following * format: \t\t\t[\t\t\t\t] * The Cutover Date is given in SimpleDateFormat's 'yyyy-MM-dd-HH-mm-ss' format in the GMT time zone. */ @@ -68,7 +69,7 @@ public class ValidateISO4217 { // Input golden-data file private static final File dataFile = new File(System.getProperty( - "test.src", "."), "tablea1.txt"); + "test.src", "."), "ISO4217-list-one.txt"); // Code statuses private static final byte UNDEFINED = 0; private static final byte DEFINED = 1; @@ -89,7 +90,7 @@ public class ValidateISO4217 { + "DEM-EEK-ESP-FIM-FRF-GHC-GRD-GWP-HRK-IEP-ITL-LTL-LUF-LVL-MGF-MRO-MTL-MXV-MZM-NLG-" + "PTE-ROL-RUR-SDD-SIT-SLL-SKK-SRG-STD-TMM-TPE-TRL-VEF-UYI-USN-USS-VEB-VED-" + "XAG-XAU-XBA-XBB-XBC-XBD-XDR-XFO-XFU-XPD-XPT-XSU-XTS-XUA-XXX-" - + "YUM-ZMK-ZWD-ZWN-ZWR"; + + "YUM-ZMK-ZWD-ZWL-ZWN-ZWR"; private static final String[][] extraCodes = { /* Defined in ISO 4217 list, but don't have code and minor unit info. */ {"AQ", "", "", "0"}, // Antarctica diff --git a/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java b/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java index d0141b304a8..cb3d4dde914 100644 --- a/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java +++ b/test/jdk/java/util/Locale/LanguageSubtagRegistryTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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,8 +25,9 @@ * @test * @bug 8025703 8040211 8191404 8203872 8222980 8225435 8241082 8242010 8247432 * 8258795 8267038 8287180 8302512 8304761 8306031 8308021 8313702 8318322 + * 8327631 8332424 8334418 * @summary Checks the IANA language subtag registry data update - * (LSR Revision: 2023-10-16) with Locale and Locale.LanguageRange + * (LSR Revision: 2024-06-14) with Locale and Locale.LanguageRange * class methods. * @run main LanguageSubtagRegistryTest */ diff --git a/test/jdk/java/util/concurrent/ConcurrentHashMap/ToArray.java b/test/jdk/java/util/concurrent/ConcurrentHashMap/ToArray.java index a200d47b5dc..7d4ab6b45ea 100644 --- a/test/jdk/java/util/concurrent/ConcurrentHashMap/ToArray.java +++ b/test/jdk/java/util/concurrent/ConcurrentHashMap/ToArray.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, 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,8 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import java.util.stream.IntStream; public class ToArray { @@ -43,63 +45,67 @@ public static void main(String[] args) throws Throwable { } static void executeTest() throws Throwable { - final Throwable[] throwable = new Throwable[1]; - final ConcurrentHashMap m = new ConcurrentHashMap<>(); + ExecutorService executor = Executors.newCachedThreadPool(); + try { + final Throwable[] throwable = new Throwable[1]; + final ConcurrentHashMap m = new ConcurrentHashMap<>(); - // Number of workers equal to the number of processors - // Each worker will put globally unique keys into the map - final int nWorkers = Runtime.getRuntime().availableProcessors(); - final int sizePerWorker = 1024; - final int maxSize = nWorkers * sizePerWorker; + // Number of workers equal to the number of processors + // Each worker will put globally unique keys into the map + final int nWorkers = Runtime.getRuntime().availableProcessors(); + final int sizePerWorker = 1024; + final int maxSize = nWorkers * sizePerWorker; - // The foreman keeps checking that the size of the arrays - // obtained from the key and value sets is never less than the - // previously observed size and is never greater than the maximum size - // NOTE: these size constraints are not specific to toArray and are - // applicable to any form of traversal of the collection views - CompletableFuture foreman = CompletableFuture.runAsync(new Runnable() { - private int prevSize = 0; + // The foreman keeps checking that the size of the arrays + // obtained from the key and value sets is never less than the + // previously observed size and is never greater than the maximum size + // NOTE: these size constraints are not specific to toArray and are + // applicable to any form of traversal of the collection views + CompletableFuture foreman = CompletableFuture.runAsync(new Runnable() { + private int prevSize = 0; - private boolean checkProgress(Object[] a) { - int size = a.length; - if (size < prevSize) throw new RuntimeException("WRONG WAY"); - if (size > maxSize) throw new RuntimeException("OVERSHOOT"); - if (size == maxSize) return true; - prevSize = size; - return false; - } + private boolean checkProgress(Object[] a) { + int size = a.length; + if (size < prevSize) throw new RuntimeException("WRONG WAY"); + if (size > maxSize) throw new RuntimeException("OVERSHOOT"); + if (size == maxSize) return true; + prevSize = size; + return false; + } - @Override - public void run() { - try { - Integer[] empty = new Integer[0]; - while (true) { - if (checkProgress(m.values().toArray())) return; - if (checkProgress(m.keySet().toArray())) return; - if (checkProgress(m.values().toArray(empty))) return; - if (checkProgress(m.keySet().toArray(empty))) return; + @Override + public void run() { + try { + Integer[] empty = new Integer[0]; + while (true) { + if (checkProgress(m.values().toArray())) return; + if (checkProgress(m.keySet().toArray())) return; + if (checkProgress(m.values().toArray(empty))) return; + if (checkProgress(m.keySet().toArray(empty))) return; + } + } catch (Throwable t) { + throwable[0] = t; } } - catch (Throwable t) { - throwable[0] = t; - } - } - }); + }, executor); - // Create workers - // Each worker will put globally unique keys into the map - CompletableFuture[] workers = IntStream.range(0, nWorkers). - mapToObj(w -> CompletableFuture.runAsync(() -> { - for (int i = 0, o = w * sizePerWorker; i < sizePerWorker; i++) - m.put(o + i, i); - })). - toArray(CompletableFuture[]::new); + // Create workers + // Each worker will put globally unique keys into the map + CompletableFuture[] workers = IntStream.range(0, nWorkers). + mapToObj(w -> CompletableFuture.runAsync(() -> { + for (int i = 0, o = w * sizePerWorker; i < sizePerWorker; i++) + m.put(o + i, i); + }, executor)). + toArray(CompletableFuture[]::new); - // Wait for workers and then foreman to complete - CompletableFuture.allOf(workers).join(); - foreman.join(); + // Wait for workers and then foreman to complete + CompletableFuture.allOf(workers).join(); + foreman.join(); - if (throwable[0] != null) - throw throwable[0]; + if (throwable[0] != null) + throw throwable[0]; + } finally { + executor.shutdownNow(); + } } } diff --git a/test/jdk/java/util/zip/DeflateIn_InflateOut.java b/test/jdk/java/util/zip/DeflateIn_InflateOut.java index dd69a7773eb..bce10c30b05 100644 --- a/test/jdk/java/util/zip/DeflateIn_InflateOut.java +++ b/test/jdk/java/util/zip/DeflateIn_InflateOut.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,8 +42,6 @@ public class DeflateIn_InflateOut { private static InflaterOutputStream ios; private static void reset() { - new Random(new Date().getTime()).nextBytes(data); - bais = new ByteArrayInputStream(data); dis = new DeflaterInputStream(bais); @@ -218,6 +216,8 @@ private static void SkipBytes() throws Throwable { public static void realMain(String[] args) throws Throwable { + new Random(new Date().getTime()).nextBytes(data); + ArrayReadWrite(); ArrayReadByteWrite(); diff --git a/test/jdk/javax/crypto/Cipher/InvalidKeyExceptionTest.java b/test/jdk/javax/crypto/Cipher/InvalidKeyExceptionTest.java new file mode 100644 index 00000000000..21b10624cfc --- /dev/null +++ b/test/jdk/javax/crypto/Cipher/InvalidKeyExceptionTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2024, 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 8335803 + * @summary Test the Cipher.init methods to handle un-extractable RSA key + * @run main/othervm InvalidKeyExceptionTest ENCRYPT_MODE + * @run main/othervm InvalidKeyExceptionTest DECRYPT_MODE + * @author Alexey Bakhtin + */ + +import java.security.InvalidKeyException; +import java.security.PrivateKey; +import javax.crypto.Cipher; + +public class InvalidKeyExceptionTest { + + public static void main(String[] args) throws Exception { + if (args.length != 1) { + throw new Exception("Encryption mode required"); + } + + int mode = 0; + switch(args[0]) { + case "ENCRYPT_MODE": + mode = Cipher.ENCRYPT_MODE; + break; + case "DECRYPT_MODE": + mode = Cipher.DECRYPT_MODE; + break; + } + + Cipher c = Cipher.getInstance("RSA/ECB/PKCS1Padding", "SunJCE"); + try { + c.init(mode, new PrivateKey() { + @Override + public String getAlgorithm() { + return "RSA"; + } + @Override + public String getFormat() { + return null; + } + @Override + public byte[] getEncoded() { + return null; + } + }); + } catch (InvalidKeyException ike) { + // expected exception + return; + } catch (Exception e) { + throw new RuntimeException("Unexpected exception: " + e); + } + new RuntimeException("InvalidKeyException should be thown"); + } +} diff --git a/test/jdk/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java b/test/jdk/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java index 41028039b78..08ea48807c4 100644 --- a/test/jdk/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java +++ b/test/jdk/javax/management/remote/mandatory/connection/DefaultAgentFilterTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2024, 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 @@ -112,7 +112,7 @@ public synchronized void start() throws Exception { AtomicBoolean error = new AtomicBoolean(false); AtomicBoolean bindError = new AtomicBoolean(false); // The predicate below tries to recognise failures. On a port clash, it sees e.g. - // Error: Exception thrown by the agent : java.rmi.server.ExportException: Port already in use: 46481; nested exception is: + // Error: Exception thrown by the agent: java.rmi.server.ExportException: Port already in use: 46481; nested exception is: // ...and will never see "main enter" from TestApp. p = ProcessTools.startProcess( TEST_APP_NAME + "{" + name + "}", diff --git a/test/jdk/javax/naming/module/RunBasic.java b/test/jdk/javax/naming/module/RunBasic.java index 54b77e23883..512062de409 100644 --- a/test/jdk/javax/naming/module/RunBasic.java +++ b/test/jdk/javax/naming/module/RunBasic.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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,8 +27,11 @@ import jdk.test.lib.process.ProcessTools; import java.io.IOException; +import java.net.InetAddress; import java.nio.file.Files; import java.nio.file.Path; +import java.time.Duration; +import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -65,6 +68,8 @@ public class RunBasic { private static final List JAVA_CMDS; + static final String HOST_NAME = InetAddress.getLoopbackAddress().getHostName(); + static { String javaPath = JDKToolFinder.getJDKTool("java"); @@ -85,11 +90,17 @@ public static void main(String[] args) throws Throwable { prepareModule("test", "--module-source-path", Path.of(TEST_SRC, "src").toString()); + System.out.println("Hostname: [" + HOST_NAME + "]"); + // run tests - runTest("java.desktop", "test.StoreObject"); - runTest("person", "test.StorePerson"); - runTest("fruit", "test.StoreFruit"); - runTest("hello", "test.StoreRemote"); + runTest("java.desktop", "test.StoreObject", + "-Dcom.sun.jndi.ldap.object.trustSerialData=true"); + runTest("person", "test.StorePerson", + "-Dcom.sun.jndi.ldap.object.trustSerialData=true"); + runTest("fruit", "test.StoreFruit", + "-Dcom.sun.jndi.ldap.object.trustSerialData=true"); + runTest("hello", "test.StoreRemote", + "-Dcom.sun.jndi.ldap.object.trustSerialData=true"); runTest("foo", "test.ConnectWithFoo"); runTest("authz", "test.ConnectWithAuthzId"); runTest("ldapv4", "test.ReadByUrl"); @@ -98,9 +109,12 @@ public static void main(String[] args) throws Throwable { private static void prepareModule(String mod, String... opts) throws IOException { System.out.println("Preparing the '" + mod + "' module..."); + long start = System.nanoTime(); makeDir("mods", mod); CompilerUtils.compile(Path.of(TEST_SRC, "src", mod), Path.of("mods", (mod.equals("test") ? "" : mod)), opts); + Duration duration = Duration.ofNanos(System.nanoTime() - start); + System.out.println("completed: duration - " + duration ); } private static void makeDir(String first, String... more) @@ -108,10 +122,19 @@ private static void makeDir(String first, String... more) Files.createDirectories(Path.of(first, more)); } - private static void runTest(String desc, String clsName) throws Throwable { + private static void runTest(String desc, String clsName, String... additionalVmOpts) throws Throwable { + List opts = new ArrayList<>(); + opts.add("-Dtest.src=" + TEST_SRC); + for (String opt : additionalVmOpts) { + opts.add(opt); + } + opts.add("-p"); + opts.add("mods"); + opts.add("-m"); + opts.add("test/" + clsName); + opts.add("ldap://" + HOST_NAME + "/dc=ie,dc=oracle,dc=com"); System.out.println("Running with the '" + desc + "' module..."); - runJava("-Dtest.src=" + TEST_SRC, "-p", "mods", "-m", "test/" + clsName, - "ldap://localhost/dc=ie,dc=oracle,dc=com"); + runJava(opts.toArray(String[]::new)); } private static void runJava(String... opts) throws Throwable { diff --git a/test/jdk/javax/naming/module/src/test/test/ConnectWithAuthzId.java b/test/jdk/javax/naming/module/src/test/test/ConnectWithAuthzId.java index 27e8e49b43d..3a50981f14e 100644 --- a/test/jdk/javax/naming/module/src/test/test/ConnectWithAuthzId.java +++ b/test/jdk/javax/naming/module/src/test/test/ConnectWithAuthzId.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -29,10 +29,10 @@ package test; +import java.io.PrintStream; import java.net.*; import java.util.*; import javax.naming.*; -import javax.naming.directory.*; import javax.naming.ldap.*; import org.example.authz.AuthzIdRequestControl; @@ -40,12 +40,18 @@ public class ConnectWithAuthzId { + static { + final PrintStream out = new PrintStream(System.out, true); + final PrintStream err = new PrintStream(System.err, true); + + System.setOut(out); + System.setErr(err); + } + // LDAP capture file private static final String LDAP_CAPTURE_FILE = System.getProperty("test.src") + "/src/test/test/ConnectWithAuthzId.ldap"; - // LDAPServer socket - private static ServerSocket serverSocket; public static void main(String[] args) throws Exception { @@ -61,74 +67,77 @@ public static void main(String[] args) throws Exception { System.err.println(" is the LDAP URL of the parent entry\n"); System.err.println("example:"); System.err.println(" java ConnectWithAuthzId ldap://oasis/o=airius.com"); - return; + throw new IllegalArgumentException(); } /* * Launch the LDAP server with the ConnectWithAuthzId.ldap capture file */ - serverSocket = new ServerSocket(0); - new Thread(new Runnable() { - @Override - public void run() { - try { - new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); - } catch (Exception e) { - System.out.println("ERROR: unable to launch LDAP server"); - e.printStackTrace(); - } + try (ServerSocket serverSocket = new ServerSocket()) { + serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + new Thread(new Runnable() { + @Override + public void run() { + try { + new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); + } catch (Exception e) { + System.out.println("ERROR: unable to launch LDAP server"); + e.printStackTrace(); + } + } + }).start(); + + /* + * Connect to the LDAP directory + */ + + Hashtable env = new Hashtable<>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + URI ldapUri = new URI(args[0]); + if (ldapUri.getPort() == -1) { + ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), + serverSocket.getLocalPort(), ldapUri.getPath(), null, null); + } + env.put(Context.PROVIDER_URL, ldapUri.toString()); + env.put(Context.SECURITY_AUTHENTICATION, "simple"); + env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=ie,dc=oracle,dc=com"); + env.put(Context.SECURITY_CREDENTIALS, "changeit"); + env.put(LdapContext.CONTROL_FACTORIES, + "org.example.authz.AuthzIdResponseControlFactory"); + if (args[args.length - 1].equalsIgnoreCase("-trace")) { + env.put("com.sun.jndi.ldap.trace.ber", System.out); } - }).start(); - - /* - * Connect to the LDAP directory - */ - - Hashtable env = new Hashtable<>(); - env.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); - URI ldapUri = new URI(args[0]); - if (ldapUri.getPort() == -1) { - ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), - serverSocket.getLocalPort(), ldapUri.getPath(), null, null); - } - env.put(Context.PROVIDER_URL, ldapUri.toString()); - env.put(Context.SECURITY_AUTHENTICATION, "simple"); - env.put(Context.SECURITY_PRINCIPAL, "cn=admin,dc=ie,dc=oracle,dc=com"); - env.put(Context.SECURITY_CREDENTIALS, "changeit"); - env.put(LdapContext.CONTROL_FACTORIES, - "org.example.authz.AuthzIdResponseControlFactory"); - if (args[args.length - 1].equalsIgnoreCase("-trace")) { - env.put("com.sun.jndi.ldap.trace.ber", System.out); - } - System.out.println("ConnectWithAuthzId: connecting to " + ldapUri); - LdapContext ctx = null; - Control[] connectionControls = { new AuthzIdRequestControl(false) }; - - try { - ctx = new InitialLdapContext(env, connectionControls); - System.out.println("ConnectWithAuthzId: connected"); - // Retrieve the response controls - Control[] responseControls = ctx.getResponseControls(); - if (responseControls != null) { - for (Control responseControl : responseControls) { - System.out.println("ConnectWithAuthzId: received response" + - " control: " + responseControl.getID()); - if (responseControl instanceof AuthzIdResponseControl) { - AuthzIdResponseControl authzId = - (AuthzIdResponseControl)responseControl; - System.out.println("ConnectWithAuthzId: identity is " + - authzId.getIdentity()); + System.out.println("ConnectWithAuthzId: connecting to " + ldapUri); + LdapContext ctx = null; + Control[] connectionControls = { new AuthzIdRequestControl(false) }; + + try { + ctx = new InitialLdapContext(env, connectionControls); + System.out.println("ConnectWithAuthzId: connected"); + // Retrieve the response controls + Control[] responseControls = ctx.getResponseControls(); + if (responseControls != null) { + for (Control responseControl : responseControls) { + System.out.println("ConnectWithAuthzId: received response" + + " control: " + responseControl.getID()); + if (responseControl instanceof AuthzIdResponseControl) { + AuthzIdResponseControl authzId = + (AuthzIdResponseControl)responseControl; + System.out.println("ConnectWithAuthzId: identity is " + + authzId.getIdentity()); + } } } - } - } catch (NamingException e) { - System.err.println("ConnectWithAuthzId: error connecting " + e); - } finally { - if (ctx != null) { - ctx.close(); + } catch (NamingException e) { + System.err.println("ConnectWithAuthzId: error connecting " + e); + throw e; + } finally { + if (ctx != null) { + ctx.close(); + } } } } diff --git a/test/jdk/javax/naming/module/src/test/test/ConnectWithFoo.java b/test/jdk/javax/naming/module/src/test/test/ConnectWithFoo.java index c14e4f4f31c..41108e2c6f6 100644 --- a/test/jdk/javax/naming/module/src/test/test/ConnectWithFoo.java +++ b/test/jdk/javax/naming/module/src/test/test/ConnectWithFoo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -28,6 +28,7 @@ package test; +import java.io.PrintStream; import java.net.*; import java.util.*; import javax.naming.*; @@ -38,11 +39,17 @@ public class ConnectWithFoo { + static { + final PrintStream out = new PrintStream(System.out, true); + final PrintStream err = new PrintStream(System.err, true); + + System.setOut(out); + System.setErr(err); + } + // LDAP capture file private static final String LDAP_CAPTURE_FILE = System.getProperty("test.src") + "/src/test/test/ConnectWithFoo.ldap"; - // LDAPServer socket - private static ServerSocket serverSocket; public static void main(String[] args) throws Exception { @@ -58,55 +65,58 @@ public static void main(String[] args) throws Exception { System.err.println(" is the LDAP URL of the parent entry\n"); System.err.println("example:"); System.err.println(" java ConnectWithFoo ldap://oasis/o=airius.com"); - return; + throw new IllegalArgumentException(); } /* * Launch the LDAP server with the ConnectWithFoo.ldap capture file */ - serverSocket = new ServerSocket(0); - new Thread(new Runnable() { - @Override - public void run() { - try { - new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); - } catch (Exception e) { - System.out.println("ERROR: unable to launch LDAP server"); - e.printStackTrace(); - } + try (ServerSocket serverSocket = new ServerSocket()) { + serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + new Thread(new Runnable() { + @Override + public void run() { + try { + new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); + } catch (Exception e) { + System.out.println("ERROR: unable to launch LDAP server"); + e.printStackTrace(); + } + } + }).start(); + + /* + * Connect to the LDAP directory + */ + + Hashtable env = new Hashtable<>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + URI ldapUri = new URI(args[0]); + if (ldapUri.getPort() == -1) { + ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), + serverSocket.getLocalPort(), ldapUri.getPath(), null, null); + } + env.put(Context.PROVIDER_URL, ldapUri.toString()); + if (args[args.length - 1].equalsIgnoreCase("-trace")) { + env.put("com.sun.jndi.ldap.trace.ber", System.out); } - }).start(); - - /* - * Connect to the LDAP directory - */ - - Hashtable env = new Hashtable<>(); - env.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); - URI ldapUri = new URI(args[0]); - if (ldapUri.getPort() == -1) { - ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), - serverSocket.getLocalPort(), ldapUri.getPath(), null, null); - } - env.put(Context.PROVIDER_URL, ldapUri.toString()); - if (args[args.length - 1].equalsIgnoreCase("-trace")) { - env.put("com.sun.jndi.ldap.trace.ber", System.out); - } - System.out.println("ConnectWithFoo: connecting to " + ldapUri); - LdapContext ctx = null; - Control[] connectionControls = { new FooControl(false) }; - - try { - ctx = new InitialLdapContext(env, connectionControls); - System.out.println("ConnectWithFoo: connected"); - } catch (NamingException e) { - System.err.println("ConnectWithFoo: error connecting " + e); - } finally { - if (ctx != null) { - ctx.close(); + System.out.println("ConnectWithFoo: connecting to " + ldapUri); + LdapContext ctx = null; + Control[] connectionControls = { new FooControl(false) }; + + try { + ctx = new InitialLdapContext(env, connectionControls); + System.out.println("ConnectWithFoo: connected"); + } catch (NamingException e) { + System.err.println("ConnectWithFoo: error connecting " + e); + throw e; + } finally { + if (ctx != null) { + ctx.close(); + } } } } diff --git a/test/jdk/javax/naming/module/src/test/test/ReadByUrl.java b/test/jdk/javax/naming/module/src/test/test/ReadByUrl.java index 4b68da455a3..df610dce3ca 100644 --- a/test/jdk/javax/naming/module/src/test/test/ReadByUrl.java +++ b/test/jdk/javax/naming/module/src/test/test/ReadByUrl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -28,6 +28,7 @@ package test; +import java.io.PrintStream; import java.net.*; import java.util.*; import javax.naming.*; @@ -36,11 +37,17 @@ public class ReadByUrl { + static { + final PrintStream out = new PrintStream(System.out, true); + final PrintStream err = new PrintStream(System.err, true); + + System.setOut(out); + System.setErr(err); + } + // LDAP capture file private static final String LDAP_CAPTURE_FILE = System.getProperty("test.src") + "/src/test/test/ReadByUrl.ldap"; - // LDAPServer socket - private static ServerSocket serverSocket; public static void main(String[] args) throws Exception { @@ -56,57 +63,60 @@ public static void main(String[] args) throws Exception { System.err.println(" is the LDAP URL of the parent entry\n"); System.err.println("example:"); System.err.println(" java ReadByUrl ldap://oasis/o=airius.com"); - return; + throw new IllegalArgumentException(); } /* * Launch the LDAP server with the ReadByUrl.ldap capture file */ - serverSocket = new ServerSocket(0); - new Thread(new Runnable() { - @Override - public void run() { - try { - new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); - } catch (Exception e) { - System.out.println("ERROR: unable to launch LDAP server"); - e.printStackTrace(); - } + try (ServerSocket serverSocket = new ServerSocket()) { + serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + new Thread(new Runnable() { + @Override + public void run() { + try { + new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); + } catch (Exception e) { + System.out.println("ERROR: unable to launch LDAP server"); + e.printStackTrace(); + } + } + }).start(); + + /* + * Connect to the LDAP directory + */ + + Hashtable env = new Hashtable<>(); + URI ldapUri = new URI(args[0]); + if (ldapUri.getPort() == -1) { + ldapUri = new URI("ldapv4", null, ldapUri.getHost(), + serverSocket.getLocalPort(), ldapUri.getPath(), null, null); + } + env.put(Context.PROVIDER_URL, ldapUri.toString()); + if (args[args.length - 1].equalsIgnoreCase("-trace")) { + env.put("com.sun.jndi.ldap.trace.ber", System.out); } - }).start(); - - /* - * Connect to the LDAP directory - */ - - Hashtable env = new Hashtable<>(); - URI ldapUri = new URI(args[0]); - if (ldapUri.getPort() == -1) { - ldapUri = new URI("ldapv4", null, ldapUri.getHost(), - serverSocket.getLocalPort(), ldapUri.getPath(), null, null); - } - env.put(Context.PROVIDER_URL, ldapUri.toString()); - if (args[args.length - 1].equalsIgnoreCase("-trace")) { - env.put("com.sun.jndi.ldap.trace.ber", System.out); - } - // URL context factory location for 'ldapv4://' - env.put(Context.URL_PKG_PREFIXES, "org.example"); - - System.out.println("ReadByUrl: connecting to " + ldapUri); - DirContext ctx = null; - - try { - ctx = new InitialDirContext(env); - System.out.println("ReadByUrl: connected"); - DirContext entry = (DirContext) ctx.lookup(ldapUri.toString()); - entry.close(); - } catch (NamingException e) { - System.err.println("ReadByUrl: error connecting " + e); - } finally { - if (ctx != null) { - ctx.close(); + // URL context factory location for 'ldapv4://' + env.put(Context.URL_PKG_PREFIXES, "org.example"); + + System.out.println("ReadByUrl: connecting to " + ldapUri); + DirContext ctx = null; + + try { + ctx = new InitialDirContext(env); + System.out.println("ReadByUrl: connected"); + DirContext entry = (DirContext) ctx.lookup(ldapUri.toString()); + entry.close(); + } catch (NamingException e) { + System.err.println("ReadByUrl: error connecting " + e); + throw e; + } finally { + if (ctx != null) { + ctx.close(); + } } } } diff --git a/test/jdk/javax/naming/module/src/test/test/StoreFruit.java b/test/jdk/javax/naming/module/src/test/test/StoreFruit.java index 278102cdcdf..6eaee6b6adc 100644 --- a/test/jdk/javax/naming/module/src/test/test/StoreFruit.java +++ b/test/jdk/javax/naming/module/src/test/test/StoreFruit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -29,6 +29,7 @@ package test; +import java.io.PrintStream; import java.net.*; import java.util.*; import javax.naming.*; @@ -38,18 +39,24 @@ public class StoreFruit { + static { + final PrintStream out = new PrintStream(System.out, true); + final PrintStream err = new PrintStream(System.err, true); + + System.setOut(out); + System.setErr(err); + } + + // LDAP capture file private static final String LDAP_CAPTURE_FILE = System.getProperty("test.src") + "/src/test/test/StoreFruit.ldap"; - // LDAPServer socket - private static ServerSocket serverSocket; public static void main(String[] args) throws Exception { /* * Process arguments */ - int argc = args.length; if ((argc < 1) || ((argc == 1) && (args[0].equalsIgnoreCase("-help")))) { @@ -58,97 +65,98 @@ public static void main(String[] args) throws Exception { System.err.println(" is the LDAP URL of the parent entry\n"); System.err.println("example:"); System.err.println(" java StoreFruit ldap://oasis/o=airius.com"); - return; + throw new IllegalArgumentException(); } /* * Launch the LDAP server with the StoreFruit.ldap capture file */ - - serverSocket = new ServerSocket(0); - new Thread(new Runnable() { - @Override - public void run() { - try { - new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); - } catch (Exception e) { - System.out.println("ERROR: unable to launch LDAP server"); - e.printStackTrace(); - } + try (ServerSocket serverSocket = new ServerSocket()) { + serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + new Thread(new Runnable() { + @Override + public void run() { + try { + new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); + } catch (Exception e) { + System.out.println("ERROR: unable to launch LDAP server"); + e.printStackTrace(); + } + } + }).start(); + + /* + * Store fruit objects in the LDAP directory + */ + + Hashtable env = new Hashtable<>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + URI ldapUri = new URI(args[0]); + if (ldapUri.getPort() == -1) { + ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), + serverSocket.getLocalPort(), ldapUri.getPath(), null, null); + } + env.put(Context.PROVIDER_URL, ldapUri.toString()); + if (args[args.length - 1].equalsIgnoreCase("-trace")) { + env.put("com.sun.jndi.ldap.trace.ber", System.out); } - }).start(); - /* - * Store fruit objects in the LDAP directory - */ + System.out.println("StoreFruit: connecting to " + ldapUri); + DirContext ctx = new InitialDirContext(env); + Fruit fruit = null; + String dn = "cn=myfruit"; + String dn2 = "cn=myapple"; - Hashtable env = new Hashtable<>(); - env.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); - URI ldapUri = new URI(args[0]); - if (ldapUri.getPort() == -1) { - ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), - serverSocket.getLocalPort(), ldapUri.getPath(), null, null); - } - env.put(Context.PROVIDER_URL, ldapUri.toString()); - if (args[args.length - 1].equalsIgnoreCase("-trace")) { - env.put("com.sun.jndi.ldap.trace.ber", System.out); - } + try { + fruit = new Fruit("orange"); + ctx.bind(dn, fruit); + System.out.println("StoreFruit: created entry '" + dn + "'"); + } catch (NameAlreadyBoundException e) { + System.err.println("StoreFruit: entry '" + dn + + "' already exists"); + cleanup(ctx, (String)null); + throw e; + } - System.out.println("StoreFruit: connecting to " + ldapUri); - DirContext ctx = new InitialDirContext(env); - Fruit fruit = null; - String dn = "cn=myfruit"; - String dn2 = "cn=myapple"; - - try { - fruit = new Fruit("orange"); - ctx.bind(dn, fruit); - System.out.println("StoreFruit: created entry '" + dn + "'"); - } catch (NameAlreadyBoundException e) { - System.err.println("StoreFruit: entry '" + dn + - "' already exists"); - cleanup(ctx, (String)null); - return; - } + try { + ctx.bind(dn2, new Fruit("apple")); + System.out.println("StoreFruit: created entry '" + dn2 + "'"); + } catch (NameAlreadyBoundException e) { + System.err.println("StoreFruit: entry '" + dn2 + + "' already exists"); + cleanup(ctx, dn); + throw e; + } - try { - ctx.bind(dn2, new Fruit("apple")); - System.out.println("StoreFruit: created entry '" + dn2 + "'"); - } catch (NameAlreadyBoundException e) { - System.err.println("StoreFruit: entry '" + dn2 + - "' already exists"); - cleanup(ctx, dn); - return; - } + /* + * Retrieve fruit objects from the LDAP directory + */ - /* - * Retrieve fruit objects from the LDAP directory - */ + try { + Fruit fruit2 = (Fruit) ctx.lookup(dn); + System.out.println("StoreFruit: retrieved object: " + fruit2); + } catch (NamingException e) { + System.err.println("StoreFruit: error retrieving entry '" + + dn + "' " + e); + e.printStackTrace(); + cleanup(ctx, dn, dn2); + throw e; + } - try { - Fruit fruit2 = (Fruit) ctx.lookup(dn); - System.out.println("StoreFruit: retrieved object: " + fruit2); - } catch (NamingException e) { - System.err.println("StoreFruit: error retrieving entry '" + - dn + "' " + e); - e.printStackTrace(); - cleanup(ctx, dn, dn2); - return; - } + try { + Fruit fruit3 = (Fruit) ctx.lookup(dn2); + System.out.println("StoreFruit: retrieved object: " + fruit3); + } catch (NamingException e) { + System.err.println("StoreFruit: error retrieving entry '" + + dn2 + "' " + e); + e.printStackTrace(); + cleanup(ctx, dn, dn2); + throw e; + } - try { - Fruit fruit3 = (Fruit) ctx.lookup(dn2); - System.out.println("StoreFruit: retrieved object: " + fruit3); - } catch (NamingException e) { - System.err.println("StoreFruit: error retrieving entry '" + - dn2 + "' " + e); - e.printStackTrace(); cleanup(ctx, dn, dn2); - return; } - - cleanup(ctx, dn, dn2); } /* diff --git a/test/jdk/javax/naming/module/src/test/test/StoreObject.java b/test/jdk/javax/naming/module/src/test/test/StoreObject.java index 2834321962f..8e4e82d5646 100644 --- a/test/jdk/javax/naming/module/src/test/test/StoreObject.java +++ b/test/jdk/javax/naming/module/src/test/test/StoreObject.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ package test; import java.awt.event.ActionEvent; +import java.io.PrintStream; import java.net.*; import java.util.*; import javax.naming.*; @@ -37,11 +38,17 @@ public class StoreObject { + static { + final PrintStream out = new PrintStream(System.out, true); + final PrintStream err = new PrintStream(System.err, true); + + System.setOut(out); + System.setErr(err); + } + // LDAP capture file private static final String LDAP_CAPTURE_FILE = System.getProperty("test.src") + "/src/test/test/StoreObject.ldap"; - // LDAPServer socket - private static ServerSocket serverSocket; public static void main(String[] args) throws Exception { @@ -57,96 +64,98 @@ public static void main(String[] args) throws Exception { System.err.println(" is the LDAP URL of the parent entry\n"); System.err.println("example:"); System.err.println(" java StoreObject ldap://oasis/o=airius.com"); - return; + throw new IllegalArgumentException(); } /* * Launch the LDAP server with the StoreObject.ldap capture file */ - serverSocket = new ServerSocket(0); - new Thread(new Runnable() { - @Override - public void run() { - try { - new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); - } catch (Exception e) { - System.out.println("ERROR: unable to launch LDAP server"); - e.printStackTrace(); - } + try (ServerSocket serverSocket = new ServerSocket()) { + serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + new Thread(new Runnable() { + @Override + public void run() { + try { + new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); + } catch (Exception e) { + System.out.println("ERROR: unable to launch LDAP server"); + e.printStackTrace(); + } + } + }).start(); + + /* + * Store objects in the LDAP directory + */ + + Hashtable env = new Hashtable<>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + URI ldapUri = new URI(args[0]); + if (ldapUri.getPort() == -1) { + ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), + serverSocket.getLocalPort(), ldapUri.getPath(), null, null); + } + env.put(Context.PROVIDER_URL, ldapUri.toString()); + if (args[args.length - 1].equalsIgnoreCase("-trace")) { + env.put("com.sun.jndi.ldap.trace.ber", System.out); } - }).start(); - /* - * Store objects in the LDAP directory - */ + System.out.println("StoreObject: connecting to " + ldapUri); + DirContext ctx = new InitialDirContext(env); + String dn = "cn=myevent"; + String dn2 = "cn=myevent2"; - Hashtable env = new Hashtable<>(); - env.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); - URI ldapUri = new URI(args[0]); - if (ldapUri.getPort() == -1) { - ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), - serverSocket.getLocalPort(), ldapUri.getPath(), null, null); - } - env.put(Context.PROVIDER_URL, ldapUri.toString()); - if (args[args.length - 1].equalsIgnoreCase("-trace")) { - env.put("com.sun.jndi.ldap.trace.ber", System.out); - } + try { + ctx.bind(dn, new ActionEvent("", 1, "Hello1")); + System.out.println("StoreObject: created entry '" + dn + "'"); + } catch (NameAlreadyBoundException e) { + System.err.println("StoreObject: entry '" + dn + + "' already exists"); + cleanup(ctx, (String)null); + throw e; + } - System.out.println("StoreObject: connecting to " + ldapUri); - DirContext ctx = new InitialDirContext(env); - String dn = "cn=myevent"; - String dn2 = "cn=myevent2"; - - try { - ctx.bind(dn, new ActionEvent("", 1, "Hello1")); - System.out.println("StoreObject: created entry '" + dn + "'"); - } catch (NameAlreadyBoundException e) { - System.err.println("StoreObject: entry '" + dn + - "' already exists"); - cleanup(ctx, (String)null); - return; - } + try { + ctx.bind(dn2, new ActionEvent("", 2, "Hello2")); + System.out.println("StoreObject: created entry '" + dn2 + "'"); + } catch (NameAlreadyBoundException e) { + System.err.println("StoreObject: entry '" + dn2 + + "' already exists"); + cleanup(ctx, dn); + throw e; + } - try { - ctx.bind(dn2, new ActionEvent("", 2, "Hello2")); - System.out.println("StoreObject: created entry '" + dn2 + "'"); - } catch (NameAlreadyBoundException e) { - System.err.println("StoreObject: entry '" + dn2 + - "' already exists"); - cleanup(ctx, dn); - return; - } + /* + * Retrieve objects from the LDAP directory + */ - /* - * Retrieve objects from the LDAP directory - */ + try { + ActionEvent b = (ActionEvent) ctx.lookup(dn); + System.out.println("StoreObject: retrieved object: " + b); + } catch (NamingException e) { + System.err.println("StoreObject: error retrieving entry '" + + dn + "' " + e); + e.printStackTrace(); + cleanup(ctx, dn, dn2); + throw e; + } - try { - ActionEvent b = (ActionEvent) ctx.lookup(dn); - System.out.println("StoreObject: retrieved object: " + b); - } catch (NamingException e) { - System.err.println("StoreObject: error retrieving entry '" + - dn + "' " + e); - e.printStackTrace(); - cleanup(ctx, dn, dn2); - return; - } + try { + ActionEvent t = (ActionEvent) ctx.lookup(dn2); + System.out.println("StoreObject: retrieved object: " + t); + } catch (NamingException e) { + System.err.println("StoreObject: error retrieving entry '" + + dn2 + "' " + e); + e.printStackTrace(); + cleanup(ctx, dn, dn2); + throw e; + } - try { - ActionEvent t = (ActionEvent) ctx.lookup(dn2); - System.out.println("StoreObject: retrieved object: " + t); - } catch (NamingException e) { - System.err.println("StoreObject: error retrieving entry '" + - dn2 + "' " + e); - e.printStackTrace(); cleanup(ctx, dn, dn2); - return; + ctx.close(); } - - cleanup(ctx, dn, dn2); - ctx.close(); } /* diff --git a/test/jdk/javax/naming/module/src/test/test/StorePerson.java b/test/jdk/javax/naming/module/src/test/test/StorePerson.java index 4b6e174625f..722d415f3c2 100644 --- a/test/jdk/javax/naming/module/src/test/test/StorePerson.java +++ b/test/jdk/javax/naming/module/src/test/test/StorePerson.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -31,6 +31,7 @@ package test; +import java.io.PrintStream; import java.net.*; import java.util.*; import javax.naming.*; @@ -40,11 +41,17 @@ public class StorePerson { + static { + final PrintStream out = new PrintStream(System.out, true); + final PrintStream err = new PrintStream(System.err, true); + + System.setOut(out); + System.setErr(err); + } + // LDAP capture file private static final String LDAP_CAPTURE_FILE = System.getProperty("test.src") + "/src/test/test/StorePerson.ldap"; - // LDAPServer socket - private static ServerSocket serverSocket; public static void main(String[] args) throws Exception { @@ -60,122 +67,123 @@ public static void main(String[] args) throws Exception { System.err.println(" is the LDAP URL of the parent entry\n"); System.err.println("example:"); System.err.println(" java StorePerson ldap://oasis/o=airius.com"); - return; + throw new IllegalArgumentException(); } /* * Launch the LDAP server with the StorePerson.ldap capture file */ - serverSocket = new ServerSocket(0); - new Thread(new Runnable() { - @Override - public void run() { - try { - new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); - } catch (Exception e) { - System.out.println("ERROR: unable to launch LDAP server"); - e.printStackTrace(); - } + try (ServerSocket serverSocket = new ServerSocket()) { + serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + new Thread(new Runnable() { + @Override + public void run() { + try { + new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); + } catch (Exception e) { + System.out.println("ERROR: unable to launch LDAP server"); + e.printStackTrace(); + } + } + }).start(); + + /* + * Store Person objects in the LDAP directory + */ + + Hashtable env = new Hashtable<>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + URI ldapUri = new URI(args[0]); + if (ldapUri.getPort() == -1) { + ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), + serverSocket.getLocalPort(), ldapUri.getPath(), null, null); + } + env.put(Context.PROVIDER_URL, ldapUri.toString()); + if (args[args.length - 1].equalsIgnoreCase("-trace")) { + env.put("com.sun.jndi.ldap.trace.ber", System.out); } - }).start(); - /* - * Store Person objects in the LDAP directory - */ + // Specify the factory classname explicitly + env.put(Context.STATE_FACTORIES, "org.example.person.PersonFactory"); + env.put(Context.OBJECT_FACTORIES, "org.example.person.PersonFactory"); - Hashtable env = new Hashtable<>(); - env.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); - URI ldapUri = new URI(args[0]); - if (ldapUri.getPort() == -1) { - ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), - serverSocket.getLocalPort(), ldapUri.getPath(), null, null); - } - env.put(Context.PROVIDER_URL, ldapUri.toString()); - if (args[args.length - 1].equalsIgnoreCase("-trace")) { - env.put("com.sun.jndi.ldap.trace.ber", System.out); - } + System.out.println("StorePerson: connecting to " + ldapUri); + DirContext ctx = new InitialDirContext(env); + Person person = null; + String name = "John Smith"; + String dn = "cn=" + name; - // Specify the factory classname explicitly - env.put(Context.STATE_FACTORIES, "org.example.person.PersonFactory"); - env.put(Context.OBJECT_FACTORIES, "org.example.person.PersonFactory"); - - System.out.println("StorePerson: connecting to " + ldapUri); - DirContext ctx = new InitialDirContext(env); - Person person = null; - String name = "John Smith"; - String dn = "cn=" + name; - - try { - person = new Person(name, "Smith"); - person.setMailAddress("jsmith@smith.com"); - ctx.bind(dn, person); - System.out.println("StorePerson: created entry '" + dn + "'"); - } catch (NameAlreadyBoundException e) { - System.err.println("StorePerson: entry '" + dn + - "' already exists"); - cleanup(ctx, (String)null); - return; - } + try { + person = new Person(name, "Smith"); + person.setMailAddress("jsmith@smith.com"); + ctx.bind(dn, person); + System.out.println("StorePerson: created entry '" + dn + "'"); + } catch (NameAlreadyBoundException e) { + System.err.println("StorePerson: entry '" + dn + + "' already exists"); + cleanup(ctx, (String)null); + throw e; + } - name = "Jill Smyth"; - String dn2 = "cn=" + name; - Person person2 = new Person(name, "Smyth"); - person2.setMailAddress("jsmyth@smith.com"); - - try { - ctx.bind(dn2, person2); - System.out.println("StorePerson: created entry '" + dn2 + "'"); - } catch (NameAlreadyBoundException e) { - System.err.println("StorePerson: entry '" + dn2 + - "' already exists"); - cleanup(ctx, dn); - return; - } + name = "Jill Smyth"; + String dn2 = "cn=" + name; + Person person2 = new Person(name, "Smyth"); + person2.setMailAddress("jsmyth@smith.com"); - /* - * Retrieve Person objects from the LDAP directory - */ + try { + ctx.bind(dn2, person2); + System.out.println("StorePerson: created entry '" + dn2 + "'"); + } catch (NameAlreadyBoundException e) { + System.err.println("StorePerson: entry '" + dn2 + + "' already exists"); + cleanup(ctx, dn); + throw e; + } - try { - Person person3 = (Person) ctx.lookup(dn); - System.out.println("StorePerson: retrieved object: " + person3); - if (person.getAttributes().equals(person3.getAttributes())) { - System.out.println( - "StorePerson: retrieved person matches original"); - } else { - System.out.println( - "StorePerson: retrieved person does NOT match original"); + /* + * Retrieve Person objects from the LDAP directory + */ + + try { + Person person3 = (Person) ctx.lookup(dn); + System.out.println("StorePerson: retrieved object: " + person3); + if (person.getAttributes().equals(person3.getAttributes())) { + System.out.println( + "StorePerson: retrieved person matches original"); + } else { + System.out.println( + "StorePerson: retrieved person does NOT match original"); + } + } catch (NamingException e) { + System.err.println("StorePerson: error retrieving entry '" + + dn + "' " + e); + e.printStackTrace(); + cleanup(ctx, dn, dn2); + throw e; } - } catch (NamingException e) { - System.err.println("StorePerson: error retrieving entry '" + - dn + "' " + e); - e.printStackTrace(); - cleanup(ctx, dn, dn2); - return; - } - try { - Person person4 = (Person) ctx.lookup(dn2); - System.out.println("StorePerson: retrieved object: " + person4); - if (person2.getAttributes().equals(person4.getAttributes())) { - System.out.println( - "StorePerson: retrieved person matches original"); - } else { - System.out.println( - "StorePerson: retrieved person does NOT match original"); + try { + Person person4 = (Person) ctx.lookup(dn2); + System.out.println("StorePerson: retrieved object: " + person4); + if (person2.getAttributes().equals(person4.getAttributes())) { + System.out.println( + "StorePerson: retrieved person matches original"); + } else { + System.out.println( + "StorePerson: retrieved person does NOT match original"); + } + } catch (NamingException e) { + System.err.println("StorePerson: error retrieving entry '" + + dn2 + "' " + e); + e.printStackTrace(); + cleanup(ctx, dn, dn2); + throw e; } - } catch (NamingException e) { - System.err.println("StorePerson: error retrieving entry '" + - dn2 + "' " + e); - e.printStackTrace(); + cleanup(ctx, dn, dn2); - return; } - - cleanup(ctx, dn, dn2); - return; } /* diff --git a/test/jdk/javax/naming/module/src/test/test/StoreRemote.java b/test/jdk/javax/naming/module/src/test/test/StoreRemote.java index 95dea1bd327..e8ee241d580 100644 --- a/test/jdk/javax/naming/module/src/test/test/StoreRemote.java +++ b/test/jdk/javax/naming/module/src/test/test/StoreRemote.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,14 +40,19 @@ public class StoreRemote { + static { + final PrintStream out = new PrintStream(System.out, true); + final PrintStream err = new PrintStream(System.err, true); + + System.setOut(out); + System.setErr(err); + } + // LDAP capture file private static final String LDAP_CAPTURE_FILE = System.getProperty("test.src") + "/src/test/test/StoreRemote.ldap"; - // LDAPServer socket - private static ServerSocket serverSocket; public static void main(String[] args) throws Exception { - /* * Process arguments */ @@ -60,84 +65,86 @@ public static void main(String[] args) throws Exception { System.err.println(" is the LDAP URL of the parent entry\n"); System.err.println("example:"); System.err.println(" java StoreRemote ldap://oasis/o=airius.com"); - return; + throw new IllegalArgumentException(); } /* * Launch the LDAP server with the StoreRemote.ldap capture file */ - serverSocket = new ServerSocket(0); - new Thread(new Runnable() { - @Override - public void run() { - try { - new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); - } catch (Exception e) { - System.out.println("ERROR: unable to launch LDAP server"); - e.printStackTrace(); - } + try (ServerSocket serverSocket = new ServerSocket()){ + serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + new Thread(new Runnable() { + @Override + public void run() { + try { + new LDAPServer(serverSocket, LDAP_CAPTURE_FILE); + } catch (Exception e) { + System.out.println("ERROR: unable to launch LDAP server"); + e.printStackTrace(); + } + } + }).start(); + + /* + * Store a Remote object in the LDAP directory + */ + + Hashtable env = new Hashtable<>(); + env.put(Context.INITIAL_CONTEXT_FACTORY, + "com.sun.jndi.ldap.LdapCtxFactory"); + URI ldapUri = new URI(args[0]); + if (ldapUri.getPort() == -1) { + ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), + serverSocket.getLocalPort(), ldapUri.getPath(), null, null); + } + env.put(Context.PROVIDER_URL, ldapUri.toString()); + if (args[args.length - 1].equalsIgnoreCase("-trace")) { + env.put("com.sun.jndi.ldap.trace.ber", System.out); } - }).start(); - - /* - * Store a Remote object in the LDAP directory - */ - - Hashtable env = new Hashtable<>(); - env.put(Context.INITIAL_CONTEXT_FACTORY, - "com.sun.jndi.ldap.LdapCtxFactory"); - URI ldapUri = new URI(args[0]); - if (ldapUri.getPort() == -1) { - ldapUri = new URI(ldapUri.getScheme(), null, ldapUri.getHost(), - serverSocket.getLocalPort(), ldapUri.getPath(), null, null); - } - env.put(Context.PROVIDER_URL, ldapUri.toString()); - if (args[args.length - 1].equalsIgnoreCase("-trace")) { - env.put("com.sun.jndi.ldap.trace.ber", System.out); - } - - System.out.println("StoreRemote: connecting to " + ldapUri); - DirContext ctx = new InitialDirContext(env); - String dn = "cn=myremote"; - try { - Hello hello = new HelloImpl(); - ctx.bind(dn, hello); - System.out.println("StoreRemote: created entry '" + dn + "'"); + System.out.println("StoreRemote: connecting to " + ldapUri); + DirContext ctx = new InitialDirContext(env); + String dn = "cn=myremote"; - // Explicitly release the RMI object - UnicastRemoteObject.unexportObject(hello, true); + try { + Hello hello = new HelloImpl(); + ctx.bind(dn, hello); + System.out.println("StoreRemote: created entry '" + dn + "'"); + + // Explicitly release the RMI object + UnicastRemoteObject.unexportObject(hello, true); + + } catch (NameAlreadyBoundException e) { + System.err.println("StoreRemote: entry '" + dn + + "' already exists"); + cleanup(ctx, (String)null); + throw e; + } - } catch (NameAlreadyBoundException e) { - System.err.println("StoreRemote: entry '" + dn + - "' already exists"); - cleanup(ctx, (String)null); - return; - } + /* + * Retrieve the Remote object from the LDAP directory + */ - /* - * Retrieve the Remote object from the LDAP directory - */ + try { + Hello obj = (Hello) ctx.lookup(dn); + System.out.println("StoreRemote: retrieved object: " + obj); + System.out.println("StoreRemote: calling Hello.sayHello()...\n" + + obj.sayHello()); - try { - Hello obj = (Hello) ctx.lookup(dn); - System.out.println("StoreRemote: retrieved object: " + obj); - System.out.println("StoreRemote: calling Hello.sayHello()...\n" + - obj.sayHello()); + // Explicitly release the RMI object + UnicastRemoteObject.unexportObject(obj, true); - // Explicitly release the RMI object - UnicastRemoteObject.unexportObject(obj, true); + } catch (NamingException e) { + System.err.println("StoreRemote: error retrieving entry '" + + dn + "' " + e); + e.printStackTrace(); + cleanup(ctx, dn); + throw e; + } - } catch (NamingException e) { - System.err.println("StoreRemote: error retrieving entry '" + - dn + "' " + e); - e.printStackTrace(); cleanup(ctx, dn); - return; } - - cleanup(ctx, dn); } /* diff --git a/test/jdk/javax/net/ssl/DTLS/CipherSuite.java b/test/jdk/javax/net/ssl/DTLS/CipherSuite.java index 773fb08d317..0b277792766 100644 --- a/test/jdk/javax/net/ssl/DTLS/CipherSuite.java +++ b/test/jdk/javax/net/ssl/DTLS/CipherSuite.java @@ -43,10 +43,10 @@ * @run main/othervm CipherSuite TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 * @run main/othervm CipherSuite TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * @run main/othervm CipherSuite TLS_RSA_WITH_AES_128_GCM_SHA256 - * @run main/othervm CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * @run main/othervm CipherSuite TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 re-enable * @run main/othervm CipherSuite TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 * @run main/othervm CipherSuite TLS_DHE_DSS_WITH_AES_128_GCM_SHA256 - * @run main/othervm CipherSuite TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * @run main/othervm CipherSuite TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 re-enable */ import javax.net.ssl.SSLEngine; diff --git a/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java b/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java index 53b50bd7464..e0991db0314 100644 --- a/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java +++ b/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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 @@ /* * @test - * @bug 8043758 + * @bug 8043758 8307383 * @summary Datagram Transport Layer Security (DTLS) * @modules java.base/sun.security.util * @library /test/lib @@ -36,6 +36,7 @@ import java.net.DatagramPacket; import java.net.SocketAddress; +import java.nio.ByteBuffer; import java.util.concurrent.atomic.AtomicBoolean; import jdk.test.lib.security.SecurityUtils; @@ -76,11 +77,34 @@ DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) { // ClientHello with cookie needInvalidRecords.set(false); System.out.println("invalidate ClientHello message"); - if (ba[ba.length - 1] == (byte)0xFF) { - ba[ba.length - 1] = (byte)0xFE; + // We will alter the compression method field in order to make the cookie + // check fail. + ByteBuffer chRec = ByteBuffer.wrap(ba); + // Skip 59 bytes past the record header (13), the handshake header (12), + // the protocol version (2), and client random (32) + chRec.position(59); + // Jump past the session ID + int len = Byte.toUnsignedInt(chRec.get()); + chRec.position(chRec.position() + len); + // Skip the cookie + len = Byte.toUnsignedInt(chRec.get()); + chRec.position(chRec.position() + len); + // Skip past cipher suites + len = Short.toUnsignedInt(chRec.getShort()); + chRec.position(chRec.position() + len); + // Read the data on the compression methods, should be at least 1 + len = Byte.toUnsignedInt(chRec.get()); + if (len >= 1) { + System.out.println("Detected compression methods (count = " + len + ")"); } else { ba[ba.length - 1] = (byte)0xFF; + throw new RuntimeException("Got zero length comp methods"); } + // alter the first comp method. + int compMethodVal = Byte.toUnsignedInt(chRec.get(chRec.position())); + System.out.println("Changing value at position " + chRec.position() + + " from " + compMethodVal + " to " + ++compMethodVal); + chRec.put(chRec.position(), (byte)compMethodVal); } return super.createHandshakePacket(ba, socketAddr); diff --git a/test/jdk/javax/net/ssl/SSLEngine/Basics.java b/test/jdk/javax/net/ssl/SSLEngine/Basics.java index 6e38c884e06..177422cb489 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/Basics.java +++ b/test/jdk/javax/net/ssl/SSLEngine/Basics.java @@ -26,8 +26,6 @@ * @bug 4495742 * @summary Add non-blocking SSL/TLS functionality, usable with any * I/O abstraction - * @ignore JSSE supported cipher suites are changed with CR 6916074, - * need to update this test case in JDK 7 soon * * This is intended to test many of the basic API calls to the SSLEngine * interface. This doesn't really exercise much of the SSL code. diff --git a/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java b/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java index ec3a96c2b35..69d1e07621f 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java +++ b/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java @@ -25,7 +25,7 @@ * @test * @bug 4948079 * @summary SSLEngineResult needs updating [none yet] - * @ignore the dependent implementation details are changed + * * @run main/othervm -Djsse.enableCBCProtection=false CheckStatus * * @author Brad Wetmore diff --git a/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java b/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java index d6e32eff5de..a18444ccc7a 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java +++ b/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java @@ -26,7 +26,6 @@ * @bug 4495742 * @summary Add non-blocking SSL/TLS functionality, usable with any * I/O abstraction - * @ignore the dependent implementation details are changed * @author Brad Wetmore * * @run main/othervm ConnectionTest diff --git a/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java b/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java index 8d60396fb91..1ddd9edfa59 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java +++ b/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java @@ -26,7 +26,7 @@ * @bug 8133632 * @summary javax.net.ssl.SSLEngine does not properly handle received * SSL fatal alerts - * @ignore the dependent implementation details are changed + * * @run main/othervm EngineCloseOnAlert */ diff --git a/test/jdk/javax/net/ssl/SSLEngine/HandshakeWithInvalidRecordVersion.java b/test/jdk/javax/net/ssl/SSLEngine/HandshakeWithInvalidRecordVersion.java new file mode 100644 index 00000000000..71119489b85 --- /dev/null +++ b/test/jdk/javax/net/ssl/SSLEngine/HandshakeWithInvalidRecordVersion.java @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2014, 2023, 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 8042449 8299870 + * @library /javax/net/ssl/templates + * @summary Verify successful handshake ignores invalid record version + * + * @run main/timeout=300 HandshakeWithInvalidRecordVersion + */ + +import javax.net.ssl.*; +import javax.net.ssl.SSLEngineResult.*; +import java.io.*; +import java.security.*; +import java.nio.*; +import java.util.Arrays; + +public class HandshakeWithInvalidRecordVersion implements SSLContextTemplate { + private static final boolean DEBUG = Boolean.getBoolean("test.debug"); + + private static final String PATH_TO_STORES = "../etc"; + private static final String KEYSTORE_FILE = "keystore"; + private static final String TRUSTSTORE_FILE = "truststore"; + + private static final String KEYSTORE_PATH = + System.getProperty("test.src", "./") + "/" + PATH_TO_STORES + + "/" + KEYSTORE_FILE; + private static final String TRUSTSTORE_PATH = + System.getProperty("test.src", "./") + "/" + PATH_TO_STORES + + "/" + TRUSTSTORE_FILE; + + public static void main(String [] args) throws Exception { + var runner = new HandshakeWithInvalidRecordVersion(); + runner.executeTest("TLSv1.2", + new String[]{"TLSv1.2"}, new String[]{"TLSv1.3", "TLSv1.2"}); + + runner.executeTest("TLSv1.2", + new String[]{"TLSv1.3", "TLSv1.2"}, new String[]{"TLSv1.2"}); + + runner.executeTest("TLSv1.3", + new String[]{"TLSv1.2", "TLSv1.3"}, new String[]{"TLSv1.3"}); + + runner.executeTest("TLSv1.3", + new String[]{"TLSv1.3"}, new String[]{"TLSv1.2", "TLSv1.3"}); + } + + + private void executeTest(String expectedProtocol, String[] clientProtocols, + String[] serverProtocols) throws Exception { + System.out.printf("Executing test%n" + + "Client protocols: %s%nServer protocols: %s%nExpected negotiated: %s%n", + Arrays.toString(clientProtocols), Arrays.toString(serverProtocols), + expectedProtocol); + + SSLEngine cliEngine = createClientSSLContext().createSSLEngine(); + cliEngine.setUseClientMode(true); + cliEngine.setEnabledProtocols(clientProtocols); + SSLEngine srvEngine = createServerSSLContext().createSSLEngine(); + srvEngine.setUseClientMode(false); + srvEngine.setEnabledProtocols(serverProtocols); + + SSLSession session = cliEngine.getSession(); + int netBufferMax = session.getPacketBufferSize(); + int appBufferMax = session.getApplicationBufferSize(); + + ByteBuffer cliToSrv = ByteBuffer.allocateDirect(netBufferMax); + ByteBuffer srvIBuff = ByteBuffer.allocateDirect(appBufferMax + 50); + ByteBuffer cliOBuff = ByteBuffer.wrap("I'm client".getBytes()); + + + System.out.println("Generating ClientHello"); + SSLEngineResult cliRes = cliEngine.wrap(cliOBuff, cliToSrv); + checkResult(cliRes, HandshakeStatus.NEED_UNWRAP); + log("Client wrap result: " + cliRes); + cliToSrv.flip(); + if (cliToSrv.limit() > 5) { + System.out.println("Setting record version to (0xa9, 0xa2)"); + cliToSrv.put(1, (byte)0xa9); + cliToSrv.put(2, (byte)0xa2); + } else { + throw new RuntimeException("ClientHello message is only " + + cliToSrv.limit() + "bytes. Expecting at least 6 bytes. "); + } + + System.out.println("Processing ClientHello"); + SSLEngineResult srv = srvEngine.unwrap(cliToSrv, srvIBuff); + checkResult(srv, HandshakeStatus.NEED_TASK); + runDelegatedTasks(srvEngine); + + finishHandshake(cliEngine, srvEngine); + + if (!cliEngine.getSession().getProtocol() + .equals(srvEngine.getSession().getProtocol()) + || !cliEngine.getSession().getProtocol().equals(expectedProtocol)) { + throw new RuntimeException("Client and server did not negotiate protocol. " + + "Expected: " + expectedProtocol + ". Negotiated: " + + cliEngine.getSession().getProtocol()); + } + } + private boolean isHandshaking(SSLEngine e) { + return (e.getHandshakeStatus() != HandshakeStatus.NOT_HANDSHAKING); + } + + private void finishHandshake(SSLEngine client, SSLEngine server) throws Exception { + boolean clientDone = false; + boolean serverDone = false; + SSLEngineResult serverResult; + SSLEngineResult clientResult; + int capacity = client.getSession().getPacketBufferSize(); + ByteBuffer emptyBuffer = ByteBuffer.allocate(capacity); + ByteBuffer serverToClient = ByteBuffer.allocate(capacity); + ByteBuffer clientToServer = ByteBuffer.allocate(capacity); + + System.out.println("Finishing handshake..."); + while (isHandshaking(client) || + isHandshaking(server)) { + + log("================"); + + clientResult = client.wrap(emptyBuffer, clientToServer); + serverResult = server.wrap(emptyBuffer, serverToClient); + + if (clientResult.getHandshakeStatus() == HandshakeStatus.FINISHED) { + clientDone = true; + } + + if (serverResult.getHandshakeStatus() == HandshakeStatus.FINISHED) { + serverDone = true; + } + + log("wrap1 = " + clientResult); + log("wrap2 = " + serverResult); + + if (clientResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = client.getDelegatedTask()) != null) { + runnable.run(); + } + } + + if (serverResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = server.getDelegatedTask()) != null) { + runnable.run(); + } + } + + clientToServer.flip(); + serverToClient.flip(); + + log("----"); + + clientResult = client.unwrap(serverToClient, emptyBuffer); + serverResult = server.unwrap(clientToServer, emptyBuffer); + + if (clientResult.getHandshakeStatus() == HandshakeStatus.FINISHED) { + clientDone = true; + } + + if (serverResult.getHandshakeStatus() == HandshakeStatus.FINISHED) { + serverDone = true; + } + + log("unwrap1 = " + clientResult); + log("unwrap2 = " + serverResult); + + if (clientResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = client.getDelegatedTask()) != null) { + runnable.run(); + } + } + + if (serverResult.getHandshakeStatus() == HandshakeStatus.NEED_TASK) { + Runnable runnable; + while ((runnable = server.getDelegatedTask()) != null) { + runnable.run(); + } + } + + clientToServer.clear(); + serverToClient.clear(); + } + + System.out.println("Handshake complete"); + + if (!clientDone || !serverDone) { + throw new RuntimeException("Both should be true:\n" + + " clientDone = " + clientDone + " serverDone = " + serverDone); + } + } + + private static void runDelegatedTasks(SSLEngine engine) { + Runnable runnable; + while ((runnable = engine.getDelegatedTask()) != null) { + log("\trunning delegated task..."); + runnable.run(); + } + } + + private static void checkResult(SSLEngineResult result, HandshakeStatus expectedStatus) { + if(result.getHandshakeStatus() != expectedStatus) { + throw new RuntimeException(String.format( + "Handshake status %s does not match expected status of %s", + result.getHandshakeStatus(), expectedStatus)); + } + } + + private static void log(Object msg) { + if (DEBUG) { + System.out.println(msg); + } + } +} diff --git a/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java b/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java index 475879a3262..5dc19f1475e 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java +++ b/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java @@ -30,7 +30,6 @@ * @test * @bug 8180643 * @summary Illegal handshake message - * @ignore the dependent implementation details are changed * @run main/othervm IllegalHandshakeMessage */ diff --git a/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java b/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java deleted file mode 100644 index aeb4c50aac9..00000000000 --- a/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * 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. - */ - -// This test case relies on updated static security property, no way to re-use -// security property in samevm/agentvm mode. - -/* - * @test - * @bug 8042449 - * @summary Issue for negative byte major record version - * @ignore the dependent implementation details are changed - * @run main/othervm IllegalRecordVersion - */ - -import javax.net.ssl.*; -import javax.net.ssl.SSLEngineResult.*; -import java.io.*; -import java.security.*; -import java.nio.*; - -public class IllegalRecordVersion { - - public static void main(String args[]) throws Exception { - SSLContext context = SSLContext.getDefault(); - - SSLEngine cliEngine = context.createSSLEngine(); - cliEngine.setUseClientMode(true); - SSLEngine srvEngine = context.createSSLEngine(); - srvEngine.setUseClientMode(false); - - SSLSession session = cliEngine.getSession(); - int netBufferMax = session.getPacketBufferSize(); - int appBufferMax = session.getApplicationBufferSize(); - - ByteBuffer cliToSrv = ByteBuffer.allocateDirect(netBufferMax); - ByteBuffer srvIBuff = ByteBuffer.allocateDirect(appBufferMax + 50); - ByteBuffer cliOBuff = ByteBuffer.wrap("I'm client".getBytes()); - - - System.out.println("client hello (record version(0xa9, 0xa2))"); - SSLEngineResult cliRes = cliEngine.wrap(cliOBuff, cliToSrv); - System.out.println("Client wrap result: " + cliRes); - cliToSrv.flip(); - if (cliToSrv.limit() > 5) { - cliToSrv.put(1, (byte)0xa9); - cliToSrv.put(2, (byte)0xa2); - } - - try { - srvEngine.unwrap(cliToSrv, srvIBuff); - throw new Exception( - "Cannot catch the unsupported record version issue"); - } catch (SSLException e) { - // get the expected exception - } - } -} diff --git a/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java b/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java index 9c633b58f70..3285479a86c 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java +++ b/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java @@ -24,8 +24,7 @@ /* * @test * @bug 4495742 - * @ignore JSSE supported cipher suites are changed with CR 6916074, - * need to update this test case in JDK 7 soon + * * @run main/timeout=180 TestAllSuites * @summary Add non-blocking SSL/TLS functionality, usable with any * I/O abstraction diff --git a/test/jdk/javax/net/ssl/TLSCommon/MFLNTest.java b/test/jdk/javax/net/ssl/TLSCommon/MFLNTest.java index ee50f21ae27..0867925f135 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/MFLNTest.java +++ b/test/jdk/javax/net/ssl/TLSCommon/MFLNTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2024, 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,7 +34,15 @@ public class MFLNTest extends SSLEngineTestCase { public static void main(String[] args) { setUpAndStartKDCIfNeeded(); System.setProperty("jsse.enableMFLNExtension", "true"); - for (int mfl = 4096; mfl >= 256; mfl /= 2) { + String testMode = System.getProperty("test.mode", "norm"); + int mflLen; + if (testMode.equals("norm_sni")) { + mflLen = 512; + } else { + mflLen = 256; + } + + for (int mfl = 4096; mfl >= mflLen; mfl /= 2) { System.out.println("==============================================" + "=============="); System.out.printf("Testsing DTLS handshake with MFL = %d%n", mfl); diff --git a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java index 7bb3e2c8d2b..855e34b57f0 100644 --- a/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java +++ b/test/jdk/javax/net/ssl/ciphersuites/DisabledAlgorithms.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8076221 8211883 + * @bug 8076221 8211883 8279164 * @summary Check if weak cipher suites are disabled * @modules jdk.crypto.ec * @run main/othervm DisabledAlgorithms default @@ -60,9 +60,9 @@ public class DisabledAlgorithms { System.getProperty("test.src", "./") + "/" + pathToStores + "/" + trustStoreFile; - // supported RC4, NULL, and anon cipher suites - // it does not contain KRB5 cipher suites because they need a KDC - private static final String[] rc4_null_anon_ciphersuites = new String[] { + // disabled RC4, NULL, anon, and ECDH cipher suites + private static final String[] disabled_ciphersuites + = new String[] { "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA", "TLS_ECDHE_RSA_WITH_RC4_128_SHA", "SSL_RSA_WITH_RC4_128_SHA", @@ -94,7 +94,19 @@ public class DisabledAlgorithms { "TLS_ECDH_anon_WITH_AES_128_CBC_SHA", "TLS_ECDH_anon_WITH_AES_256_CBC_SHA", "TLS_ECDH_anon_WITH_NULL_SHA", - "TLS_ECDH_anon_WITH_RC4_128_SHA" + "TLS_ECDH_anon_WITH_RC4_128_SHA", + "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", + "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", + "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", + "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", + "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", + "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", + "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", + "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", + "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA" }; public static void main(String[] args) throws Exception { @@ -113,9 +125,8 @@ public static void main(String[] args) throws Exception { System.out.println("jdk.tls.disabledAlgorithms = " + Security.getProperty("jdk.tls.disabledAlgorithms")); - // check if RC4, NULL, and anon cipher suites - // can't be used by default - checkFailure(rc4_null_anon_ciphersuites); + // check that disabled cipher suites can't be used by default + checkFailure(disabled_ciphersuites); break; case "empty": // reset jdk.tls.disabledAlgorithms @@ -123,9 +134,9 @@ public static void main(String[] args) throws Exception { System.out.println("jdk.tls.disabledAlgorithms = " + Security.getProperty("jdk.tls.disabledAlgorithms")); - // check if RC4, NULL, and anon cipher suites can be used - // if jdk.tls.disabledAlgorithms is empty - checkSuccess(rc4_null_anon_ciphersuites); + // check that disabled cipher suites can be used if + // jdk.{tls,certpath}.disabledAlgorithms is empty + checkSuccess(disabled_ciphersuites); break; default: throw new RuntimeException("Wrong parameter: " + args[0]); @@ -151,11 +162,12 @@ private static void checkFailure(String[] ciphersuites) throws Exception { throw new RuntimeException("Expected SSLHandshakeException " + "not thrown"); } catch (SSLHandshakeException e) { - System.out.println("Expected exception on client side: " + System.out.println("Got expected exception on client side: " + e); } } + server.stop(); while (server.isRunning()) { sleep(); } @@ -251,7 +263,6 @@ public void run() { } catch (SSLHandshakeException e) { System.out.println("Server: run: " + e); sslError = true; - stopped = true; } catch (IOException e) { if (!stopped) { System.out.println("Server: run: unexpected exception: " diff --git a/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java b/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java index 0fc9c02f2d0..caa96cdb224 100644 --- a/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java +++ b/test/jdk/javax/net/ssl/sanity/ciphersuites/CheckCipherSuites.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 4750141 4895631 8217579 8163326 + * @bug 4750141 4895631 8217579 8163326 8279164 * @summary Check enabled and supported ciphersuites are correct * @run main/othervm CheckCipherSuites default * @run main/othervm CheckCipherSuites limited @@ -50,54 +50,38 @@ public class CheckCipherSuites { // Not suite B, but we want it to position the suite early "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", - // AES_256(GCM) - ECDHE - forward screcy + // AES_256(GCM) - ECDHE - forward secrecy "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", - // AES_128(GCM) - ECDHE - forward screcy + // AES_128(GCM) - ECDHE - forward secrecy "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - // AES_256(GCM) - DHE - forward screcy + // AES_256(GCM) - DHE - forward secrecy "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", - // AES_128(GCM) - DHE - forward screcy + // AES_128(GCM) - DHE - forward secrecy "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", - // AES_256(CBC) - ECDHE - forward screcy + // AES_256(CBC) - ECDHE - forward secrecy "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", - // AES_256(CBC) - ECDHE - forward screcy + // AES_256(CBC) - ECDHE - forward secrecy "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", - // AES_256(CBC) - DHE - forward screcy + // AES_256(CBC) - DHE - forward secrecy "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", - // AES_128(CBC) - DHE - forward screcy + // AES_128(CBC) - DHE - forward secrecy "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", - // AES_256(GCM) - not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", - - // AES_128(GCM) - not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", - - // AES_256(CBC) - not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", - "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", - - // AES_128(CBC) - not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", - // AES_256(CBC) - ECDHE - using SHA "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", @@ -114,14 +98,6 @@ public class CheckCipherSuites { "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", - // AES_256(CBC) - using SHA, not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", - "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", - - // AES_128(CBC) - using SHA, not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", - // deprecated "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256", @@ -144,16 +120,10 @@ public class CheckCipherSuites { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", - "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA", @@ -175,54 +145,38 @@ public class CheckCipherSuites { // Not suite B, but we want it to position the suite early "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256", - // AES_256(GCM) - ECDHE - forward screcy + // AES_256(GCM) - ECDHE - forward secrecy "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256", - // AES_128(GCM) - ECDHE - forward screcy + // AES_128(GCM) - ECDHE - forward secrecy "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256", - // AES_256(GCM) - DHE - forward screcy + // AES_256(GCM) - DHE - forward secrecy "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384", "TLS_DHE_RSA_WITH_CHACHA20_POLY1305_SHA256", "TLS_DHE_DSS_WITH_AES_256_GCM_SHA384", - // AES_128(GCM) - DHE - forward screcy + // AES_128(GCM) - DHE - forward secrecy "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256", "TLS_DHE_DSS_WITH_AES_128_GCM_SHA256", - // AES_256(CBC) - ECDHE - forward screcy + // AES_256(CBC) - ECDHE - forward secrecy "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384", - // AES_256(CBC) - ECDHE - forward screcy + // AES_256(CBC) - ECDHE - forward secrecy "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", - // AES_256(CBC) - DHE - forward screcy + // AES_256(CBC) - DHE - forward secrecy "TLS_DHE_RSA_WITH_AES_256_CBC_SHA256", "TLS_DHE_DSS_WITH_AES_256_CBC_SHA256", - // AES_128(CBC) - DHE - forward screcy + // AES_128(CBC) - DHE - forward secrecy "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", - // AES_256(GCM) - not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384", - "TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384", - - // AES_128(GCM) - not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", - - // AES_256(CBC) - not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384", - "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384", - - // AES_128(CBC) - not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", - // AES_256(CBC) - ECDHE - using SHA "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA", @@ -239,14 +193,6 @@ public class CheckCipherSuites { "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", - // AES_256(CBC) - using SHA, not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA", - "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA", - - // AES_128(CBC) - using SHA, not forward screcy - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", - // deprecated "TLS_RSA_WITH_AES_256_GCM_SHA384", "TLS_RSA_WITH_AES_128_GCM_SHA256", @@ -269,16 +215,10 @@ public class CheckCipherSuites { "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA256", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA256", - "TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256", - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256", "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA", "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_RSA_WITH_AES_128_CBC_SHA", "TLS_DHE_DSS_WITH_AES_128_CBC_SHA", - "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA", - "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA", "TLS_RSA_WITH_AES_128_GCM_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA256", "TLS_RSA_WITH_AES_128_CBC_SHA", diff --git a/test/jdk/javax/print/PrintServiceLookup/FlushCustomClassLoader.java b/test/jdk/javax/print/PrintServiceLookup/FlushCustomClassLoader.java index 6e0a25a69d0..4ec95fb7535 100644 --- a/test/jdk/javax/print/PrintServiceLookup/FlushCustomClassLoader.java +++ b/test/jdk/javax/print/PrintServiceLookup/FlushCustomClassLoader.java @@ -34,6 +34,9 @@ * @test * @bug 8273831 * @summary Tests custom class loader cleanup + * @library /javax/swing/regtesthelpers + * @build Util + * @run main/timeout=60/othervm -mx32m FlushCustomClassLoader */ public final class FlushCustomClassLoader { @@ -42,12 +45,8 @@ public static void main(String[] args) throws Exception { int attempt = 0; while (loader.get() != null) { - if (++attempt > 10) { - throw new RuntimeException("Too many attempts: " + attempt); - } - System.gc(); - Thread.sleep(1000); - System.out.println("Not freed, attempt: " + attempt); + Util.generateOOME(); + System.out.println("Not freed, attempt: " + attempt++); } } diff --git a/test/jdk/javax/swing/JButton/bug4234034.java b/test/jdk/javax/swing/JButton/bug4234034.java new file mode 100644 index 00000000000..e1e65345f73 --- /dev/null +++ b/test/jdk/javax/swing/JButton/bug4234034.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 1999, 2023, 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 4234034 + * @summary Tests NullPointerException when ToolTip invoked via keyboard + * @key headful + * @run main bug4234034 + */ + +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class bug4234034 { + static JFrame frame; + static JButton button; + + public static void main(String args[]) throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(100); + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("bug4323121"); + button = new JButton("Press tab, then Ctrl+F1"); + button.setToolTipText("Tooltip for button"); + frame.getContentPane().add(button); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + robot.keyPress(KeyEvent.VK_TAB); + robot.keyRelease(KeyEvent.VK_TAB); + robot.keyPress(KeyEvent.VK_CONTROL); + robot.keyPress(KeyEvent.VK_F1); + robot.keyRelease(KeyEvent.VK_F1); + robot.keyRelease(KeyEvent.VK_CONTROL); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/JButton/bug4323121.java b/test/jdk/javax/swing/JButton/bug4323121.java new file mode 100644 index 00000000000..0b352ce57eb --- /dev/null +++ b/test/jdk/javax/swing/JButton/bug4323121.java @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2000, 2023, 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 4323121 + * @summary Tests whether any button that extends JButton always + returns true for isArmed() + * @key headful + * @run main bug4323121 + */ + +import java.awt.Graphics; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.MouseEvent; +import java.awt.event.MouseListener; +import java.awt.event.MouseMotionListener; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class bug4323121 { + + static JFrame frame; + static testButton button; + static volatile Point pt; + static volatile int buttonW; + static volatile int buttonH; + static volatile boolean failed = false; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(100); + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("bug4323121"); + button = new testButton("gotcha"); + frame.getContentPane().add(button); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + pt = button.getLocationOnScreen(); + buttonW = button.getSize().width; + buttonH = button.getSize().height; + }); + robot.mouseMove(pt.x + buttonW / 2, pt.y + buttonH / 2); + robot.waitForIdle(); + if (failed) { + throw new RuntimeException("Any created button returns " + + "true for isArmed()"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static class testButton extends JButton implements MouseMotionListener, MouseListener { + public testButton(String label) { + super(label); + addMouseMotionListener(this); + addMouseListener(this); + } + + protected void paintComponent(Graphics g) { + super.paintComponent(g); + } + + protected void paintBorder(Graphics g) { + } + + public void mousePressed(MouseEvent e) { + } + + public void mouseDragged(MouseEvent e) { + } + + public void mouseMoved(MouseEvent e) { + } + + public void mouseReleased(MouseEvent e) { + } + + public void mouseEntered(MouseEvent e) { + if (getModel().isArmed()) { + failed = true; + } + } + + public void mouseExited(MouseEvent e) { + } + + public void mouseClicked(MouseEvent e) { + } + } +} diff --git a/test/jdk/javax/swing/JButton/bug4490179.java b/test/jdk/javax/swing/JButton/bug4490179.java new file mode 100644 index 00000000000..94b141e5030 --- /dev/null +++ b/test/jdk/javax/swing/JButton/bug4490179.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2002, 2023, 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 4490179 + * @summary Tests that JButton only responds to left mouse clicks. + * @key headful + * @run main bug4490179 + */ + +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.InputEvent; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.SwingUtilities; + +public class bug4490179 { + static JFrame frame; + static JButton button; + static volatile Point pt; + static volatile int buttonW; + static volatile int buttonH; + static volatile boolean passed = true; + + public static void main(String[] args) throws Exception { + Robot robot = new Robot(); + robot.setAutoDelay(100); + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("bug4490179"); + button = new JButton("Button"); + frame.getContentPane().add(button); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + passed = false; + } + }); + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + pt = button.getLocationOnScreen(); + buttonW = button.getSize().width; + buttonH = button.getSize().height; + }); + + robot.mouseMove(pt.x + buttonW / 2, pt.y + buttonH / 2); + robot.waitForIdle(); + robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON3_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON3_DOWN_MASK); + + if (!passed) { + throw new RuntimeException("Test Failed"); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/JComponent/6683775/bug6683775.java b/test/jdk/javax/swing/JComponent/6683775/bug6683775.java index c5572e83919..5c8445dc479 100644 --- a/test/jdk/javax/swing/JComponent/6683775/bug6683775.java +++ b/test/jdk/javax/swing/JComponent/6683775/bug6683775.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2021, 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 @@ -46,6 +46,10 @@ public class bug6683775 { static final int LOC = 100, SIZE = 200; + static JFrame testFrame; + static JFrame backgroundFrame; + static BufferedImage capture; + public static void main(String[] args) throws Exception { GraphicsConfiguration gc = getGC(); if (gc == null || !gc.getDevice().isWindowTranslucencySupported( @@ -53,35 +57,39 @@ public static void main(String[] args) throws Exception { return; } Robot robot = new Robot(); - final JFrame testFrame = new JFrame(gc); - - SwingUtilities.invokeAndWait(() -> { - JFrame backgroundFrame = new JFrame("Background frame"); - backgroundFrame.setUndecorated(true); - JPanel panel = new JPanel(); - panel.setBackground(Color.RED); - backgroundFrame.add(panel); - backgroundFrame.setBounds(LOC, LOC, SIZE, SIZE); - backgroundFrame.setVisible(true); - - testFrame.setUndecorated(true); - JPanel p = new JPanel(); - p.setOpaque(false); - testFrame.add(p); - setOpaque(testFrame, false); - testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - testFrame.setBounds(LOC, LOC, SIZE, SIZE); - testFrame.setVisible(true); - }); - - robot.waitForIdle(); - Thread.sleep(1500); - - //robot.getPixelColor() didn't work right for some reason - BufferedImage capture = - robot.createScreenCapture(new Rectangle(LOC, LOC, SIZE, SIZE)); - - SwingUtilities.invokeAndWait(testFrame::dispose); + + try { + SwingUtilities.invokeAndWait(() -> { + testFrame = new JFrame(gc); + backgroundFrame = new JFrame("Background frame"); + backgroundFrame.setUndecorated(true); + JPanel panel = new JPanel(); + panel.setBackground(Color.RED); + backgroundFrame.add(panel); + backgroundFrame.setBounds(LOC, LOC, SIZE, SIZE); + backgroundFrame.setVisible(true); + + testFrame.setUndecorated(true); + JPanel p = new JPanel(); + p.setOpaque(false); + testFrame.add(p); + setOpaque(testFrame, false); + testFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + testFrame.setBounds(LOC, LOC, SIZE, SIZE); + testFrame.setVisible(true); + }); + + robot.waitForIdle(); + robot.delay(1000); + + //robot.getPixelColor() didn't work right for some reason + capture = + robot.createScreenCapture(new Rectangle(LOC, LOC, SIZE, SIZE)); + + } finally { + SwingUtilities.invokeAndWait(testFrame::dispose); + SwingUtilities.invokeAndWait(backgroundFrame::dispose); + } int redRGB = Color.RED.getRGB(); if (redRGB != capture.getRGB(SIZE/2, SIZE/2)) { diff --git a/test/jdk/javax/swing/JEditorPane/EditorPaneCharset.java b/test/jdk/javax/swing/JEditorPane/EditorPaneCharset.java new file mode 100644 index 00000000000..cf2edf0e1a1 --- /dev/null +++ b/test/jdk/javax/swing/JEditorPane/EditorPaneCharset.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2024, 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.ByteArrayInputStream; +import java.io.IOException; +import java.nio.charset.Charset; + +import javax.swing.JEditorPane; +import javax.swing.text.BadLocationException; +import javax.swing.text.Document; +import javax.swing.text.Element; + +/* + * @test + * @bug 8328953 + * @summary Verifies JEditorPane.read doesn't throw ChangedCharSetException + but handles it and reads HTML in the specified encoding + * @run main EditorPaneCharset + */ + +public final class EditorPaneCharset { + private static final String CYRILLIC_TEXT = + "\u041F\u0440\u0438\u0432\u0435\u0442, \u043C\u0438\u0440!"; + private static final String HTML_CYRILLIC = + "\n" + + "\n" + + " \n" + + "\n" + + "

    " + CYRILLIC_TEXT + "

    \n" + + "\n"; + + public static void main(String[] args) throws IOException, BadLocationException { + JEditorPane editorPane = new JEditorPane(); + editorPane.setContentType("text/html"); + Document document = editorPane.getDocument(); + + // Shouldn't throw ChangedCharSetException + editorPane.read( + new ByteArrayInputStream( + HTML_CYRILLIC.getBytes( + Charset.forName("windows-1251"))), + document); + + Element root = document.getDefaultRootElement(); + Element body = root.getElement(1); + Element p = body.getElement(0); + String pText = document.getText(p.getStartOffset(), + p.getEndOffset() - p.getStartOffset() - 1); + if (!CYRILLIC_TEXT.equals(pText)) { + throw new RuntimeException("Text doesn't match"); + } + } +} diff --git a/test/jdk/javax/swing/JFileChooser/FileSystemView/Win32FolderSort.java b/test/jdk/javax/swing/JFileChooser/FileSystemView/Win32FolderSort.java new file mode 100644 index 00000000000..7ed5e0f1705 --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/FileSystemView/Win32FolderSort.java @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2024, 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.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +/* + * @test + * @bug 8305072 + * @requires (os.family == "windows") + * @modules java.desktop/sun.awt.shell + * @summary Verifies consistency of Win32ShellFolder2.compareTo + * @run main/othervm --add-opens java.desktop/sun.awt.shell=ALL-UNNAMED Win32FolderSort + */ +public class Win32FolderSort { + public static void main(String[] args) throws Exception { + Class folderManager = Class.forName("sun.awt.shell.Win32ShellFolderManager2"); + Class folder = Class.forName("sun.awt.shell.Win32ShellFolder2"); + + Method getDesktop = folderManager.getDeclaredMethod("getDesktop"); + getDesktop.setAccessible(true); + Method getPersonal = folderManager.getDeclaredMethod("getPersonal"); + getPersonal.setAccessible(true); + + Method createShellFolder = folderManager.getDeclaredMethod("createShellFolder", folder, File.class); + createShellFolder.setAccessible(true); + + Method isFileSystem = folder.getMethod("isFileSystem"); + isFileSystem.setAccessible(true); + Method isSpecial = folder.getMethod("isSpecial"); + isSpecial.setAccessible(true); + Method getChildByPath = folder.getDeclaredMethod("getChildByPath", String.class); + getChildByPath.setAccessible(true); + + File desktop = (File) getDesktop.invoke(null); + File personal = (File) getPersonal.invoke(null); + if (!((Boolean) isSpecial.invoke(personal))) { + throw new RuntimeException("personal is not special"); + } + File fakePersonal = (File) getChildByPath.invoke(desktop, personal.getPath()); + if (fakePersonal == null) { + fakePersonal = (File) createShellFolder.invoke(null, desktop, + new File(personal.getPath())); + } + if ((Boolean) isSpecial.invoke(fakePersonal)) { + throw new RuntimeException("fakePersonal is special"); + } + File homeDir = (File) createShellFolder.invoke(null, desktop, + new File(System.getProperty("user.home"))); + + File[] files = {fakePersonal, personal, homeDir}; + for (File f : files) { + if (!((Boolean) isFileSystem.invoke(f))) { + throw new RuntimeException(f + " is not on file system"); + } + } + + List errors = new ArrayList<>(2); + for (File f1 : files) { + for (File f2 : files) { + for (File f3 : files) { + String result = verifyCompareTo(f1, f2, f3); + if (result != null) { + String error = result + "\nwhere" + + "\n a = " + formatFile(f1, isSpecial) + + "\n b = " + formatFile(f2, isSpecial) + + "\n c = " + formatFile(f3, isSpecial); + errors.add(error); + } + } + } + } + + + System.out.println("Unsorted:"); + for (File f : files) { + System.out.println(formatFile(f, isSpecial)); + } + System.out.println(); + + Arrays.sort(files); + System.out.println("Sorted:"); + for (File f : files) { + System.out.println(formatFile(f, isSpecial)); + } + + + if (!errors.isEmpty()) { + System.err.println("Implementation of Win32ShellFolder2.compareTo is inconsistent:"); + errors.forEach(System.err::println); + throw new RuntimeException("Inconsistencies found: " + errors.size() + + " - " + errors.get(0)); + } + } + + /** + * Verifies consistency of {@code Comparable} implementation. + * + * @param a the first object + * @param b the second object + * @param c the third object + * @return error message if inconsistency is found, + * or {@code null } otherwise + */ + private static String verifyCompareTo(File a, File b, File c) { + // a < b & b < c => a < c + if (a.compareTo(b) < 0 && b.compareTo(c) < 0) { + if (a.compareTo(c) >= 0) { + return "a < b & b < c but a >= c"; + } + } + + // a > b & b > c => a > c + if (a.compareTo(b) > 0 && b.compareTo(c) > 0) { + if (a.compareTo(c) <= 0) { + return "a > b & b > c but a <= c"; + } + } + + // a = b & b = c => a = c + if (a.compareTo(b) == 0 && b.compareTo(c) == 0) { + if (a.compareTo(c) != 0) { + return "a = b & b = c but a != c"; + } + } + + return null; + } + + private static String formatFile(File f, Method isSpecial) + throws InvocationTargetException, IllegalAccessException { + return f + "(" + isSpecial.invoke(f) + ")"; + } +} diff --git a/test/jdk/javax/swing/JFrame/DefaultCloseOperation.java b/test/jdk/javax/swing/JFrame/DefaultCloseOperation.java new file mode 100644 index 00000000000..9b4b7b6df5e --- /dev/null +++ b/test/jdk/javax/swing/JFrame/DefaultCloseOperation.java @@ -0,0 +1,228 @@ +/* + * Copyright (c) 1998, 2023, 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.awt.Frame; +import java.awt.FlowLayout; +import java.awt.Window; +import java.awt.event.ItemEvent; +import java.awt.event.WindowEvent; +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JDialog; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; +import javax.swing.WindowConstants; + +/* + * @test + * @summary test for defaultCloseOperation property for Swing JFrame and JDialog + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual DefaultCloseOperation + */ + +public class DefaultCloseOperation extends JPanel { + + private static final String INSTRUCTIONS = "Do the following steps:\n\n" + + "- Click the \"Open Frame\" button (a TestFrame will appear)\n" + + "- On the TestFrame, select \"Close\" from the system menu (the window should go away)\n" + + "- Select \"Do Nothing\" from the \"JFrame Default Close Operation\" ComboBox\n" + + "- Click the \"Open Frame\" button\n" + + "- On the TestFrame, select \"Close\" from the system menu (the window should remain open)\n" + + "- Select \"Dispose\" from the \"JFrame Default Close Operation\" ComboBox\n" + + "- On the TestFrame, select \"Close\" from the system menu (the window should go away)\n\n\n" + + "- Click the \"Open Frame\" button\n" + + "- Click the \"Open Dialog\" button (a TestDialog will appear)\n" + + "- On the TestDialog, select \"Close\" from the system menu (the window should go away)\n" + + "- Select \"Do Nothing\" from the \"JDialog Default Close Operation\" ComboBox\n" + + "- Click the \"Open Dialog\" button\n" + + "- On the TestDialog, select \"Close\" from the system menu (the window should remain open)\n" + + "- Select \"Dispose\" from the \"JDialog Default Close Operation\" ComboBox\n" + + "- On the TestDialog, select \"Close\" from the system menu (the window should go away)"; + + JComboBox frameCloseOp; + + CloseOpDialog testDialog; + JComboBox dialogCloseOp; + + public static void main(String[] args) throws Exception { + + PassFailJFrame passFailJFrame = new PassFailJFrame.Builder() + .title("DefaultCloseOperation Manual Test") + .instructions(INSTRUCTIONS) + .testTimeOut(5) + .rows(20) + .columns(70) + .build(); + + SwingUtilities.invokeAndWait(() -> { + DefaultCloseOperation dco = new DefaultCloseOperation(); + dco.init(); + + JFrame frame = new JFrame("DefaultCloseOperation"); + frame.add(dco); + frame.setSize(500,200); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame + .positionTestWindow(frame, PassFailJFrame.Position.HORIZONTAL); + + frame.setVisible(true); + }); + + passFailJFrame.awaitAndCheck(); + } + + public void init() { + setLayout(new FlowLayout()); + + CloseOpFrame testFrame = new CloseOpFrame(); + testFrame.setLocationRelativeTo(null); + PassFailJFrame.addTestWindow(testFrame); + + add(new JLabel("JFrame Default Close Operation:")); + frameCloseOp = new JComboBox<>(); + frameCloseOp.addItem("Hide"); + frameCloseOp.addItem("Do Nothing"); + frameCloseOp.addItem("Dispose"); + frameCloseOp.addItemListener(e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + String item = (String)e.getItem(); + switch (item) { + case "Do Nothing": + testFrame + .setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + break; + case "Hide": + testFrame + .setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); + break; + case "Dispose": + testFrame + .setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + break; + } + } + }); + add(frameCloseOp); + + JButton b = new JButton("Open Frame..."); + b.addActionListener(e -> testFrame.setVisible(true)); + add(b); + + testDialog = new CloseOpDialog(testFrame); + testDialog.setLocationRelativeTo(null); + PassFailJFrame.addTestWindow(testDialog); + + add(new JLabel("JDialog Default Close Operation:")); + dialogCloseOp = new JComboBox<>(); + dialogCloseOp.addItem("Hide"); + dialogCloseOp.addItem("Do Nothing"); + dialogCloseOp.addItem("Dispose"); + dialogCloseOp.addItemListener(e -> { + if (e.getStateChange() == ItemEvent.SELECTED) { + String item = (String)e.getItem(); + switch (item) { + case "Do Nothing": + testDialog + .setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE); + break; + case "Hide": + testDialog + .setDefaultCloseOperation(WindowConstants.HIDE_ON_CLOSE); + break; + case "Dispose": + testDialog + .setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE); + break; + } + } + }); + add(dialogCloseOp); + + b = new JButton("Open Dialog..."); + b.addActionListener(e -> testDialog.setVisible(true)); + add(b); + } + + public static void verifyCloseOperation(Window window, int op) { + switch (op) { + case WindowConstants.DO_NOTHING_ON_CLOSE: + if (!window.isVisible()) { + PassFailJFrame + .forceFail("defaultCloseOperation=DoNothing failed"); + } + break; + case WindowConstants.HIDE_ON_CLOSE: + if (window.isVisible()) { + PassFailJFrame + .forceFail("defaultCloseOperation=Hide failed"); + } + break; + case WindowConstants.DISPOSE_ON_CLOSE: + if (window.isVisible() || window.isDisplayable()) { + PassFailJFrame + .forceFail("defaultCloseOperation=Dispose failed"); + } + break; + } + } +} + +class CloseOpFrame extends JFrame { + + public CloseOpFrame() { + super("DefaultCloseOperation Test"); + getContentPane().add("Center", new JLabel("Test Frame")); + pack(); + } + + protected void processWindowEvent(WindowEvent e) { + super.processWindowEvent(e); + + if (e.getID() == WindowEvent.WINDOW_CLOSING) { + DefaultCloseOperation + .verifyCloseOperation(this, getDefaultCloseOperation()); + } + } +} + +class CloseOpDialog extends JDialog { + + public CloseOpDialog(Frame owner) { + super(owner, "DefaultCloseOperation Test Dialog"); + getContentPane().add("Center", new JLabel("Test Dialog")); + pack(); + } + + protected void processWindowEvent(WindowEvent e) { + super.processWindowEvent(e); + + if (e.getID() == WindowEvent.WINDOW_CLOSING) { + DefaultCloseOperation + .verifyCloseOperation(this, getDefaultCloseOperation()); + } + } +} diff --git a/test/jdk/javax/swing/JFrame/bug4419914.java b/test/jdk/javax/swing/JFrame/bug4419914.java new file mode 100644 index 00000000000..90a8c345395 --- /dev/null +++ b/test/jdk/javax/swing/JFrame/bug4419914.java @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2001, 2024, 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 4419914 + * @summary Tests that tab movement is correct in RTL component orientation. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4419914 +*/ + +import java.awt.BorderLayout; +import java.awt.ComponentOrientation; +import javax.swing.JButton; +import javax.swing.JFrame; +import java.util.Locale; + +public class bug4419914 { + private static final String INSTRUCTIONS = + "Put the cursor at the beginning of the first text line and move the\n" + + "cursor to the right using arrow key.\n" + + "If the text is not corrupted then click Pass\n" + + "If the text disappear while cursor moves click Fail."; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Tab movement Instructions") + .instructions(INSTRUCTIONS) + .rows((int) INSTRUCTIONS.lines().count() + 2) + .columns(48) + .testUI(bug4419914::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("bug4419914"); + frame.setFocusCycleRoot(true); + frame.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + frame.setLocale(Locale.ENGLISH); + frame.enableInputMethods(false); + + frame.getContentPane().setComponentOrientation( + ComponentOrientation.RIGHT_TO_LEFT); + frame.getContentPane().setLocale(Locale.ENGLISH); + frame.getContentPane().setLayout(new BorderLayout()); + frame.add(new JButton("SOUTH"), BorderLayout.SOUTH); + frame.add(new JButton("CENTER"), BorderLayout.CENTER); + frame.add(new JButton("END"), BorderLayout.LINE_END); + frame.add(new JButton("START"), BorderLayout.LINE_START); + frame.add(new JButton("NORTH"), BorderLayout.NORTH); + frame.setSize(300, 150); + return frame; + } +} diff --git a/test/jdk/javax/swing/JList/6462008/bug6462008.java b/test/jdk/javax/swing/JList/6462008/bug6462008.java index d3058c84b01..0f3a1d1bd81 100644 --- a/test/jdk/javax/swing/JList/6462008/bug6462008.java +++ b/test/jdk/javax/swing/JList/6462008/bug6462008.java @@ -61,6 +61,7 @@ public void run() { }); robot.waitForIdle(); + robot.delay(1000); setAnchorLead(-1); robot.waitForIdle(); @@ -366,6 +367,7 @@ private static void createAndShowGUI() { frame.getContentPane().add(panel); frame.setVisible(true); + frame.setLocationRelativeTo(null); } private static void checkSelection(int... sels) throws Exception { diff --git a/test/jdk/javax/swing/JMenu/bug4143592.java b/test/jdk/javax/swing/JMenu/bug4143592.java new file mode 100644 index 00000000000..334128f39ff --- /dev/null +++ b/test/jdk/javax/swing/JMenu/bug4143592.java @@ -0,0 +1,49 @@ +/* + * Copyright (c) 1999, 2023, 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 4143592 + * @summary Tests the method add(Component, int) of JMenu for insertion + the given component to a specified position of menu + * @run main bug4143592 + */ + +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; + +public class bug4143592 { + + public static void main(String[] argv) { + JMenuBar mb = new JMenuBar(); + JMenu m = mb.add(new JMenu("Order")); + m.add("beginning"); + m.add("middle"); + m.add("end"); + m.add(new JMenuItem("in between"), 1); + if (!m.getItem(1).getText().equals("in between")) { + throw new RuntimeException("Item was inserted incorrectly."); + } + } +} diff --git a/test/jdk/javax/swing/JMenu/bug4148154.java b/test/jdk/javax/swing/JMenu/bug4148154.java new file mode 100644 index 00000000000..1da1549af19 --- /dev/null +++ b/test/jdk/javax/swing/JMenu/bug4148154.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2001, 2023, 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 4148154 + * @summary Tests that menu items created by JMenu.add(Action) method + have right HorizontalTextPosition. + * @run main bug4148154 + */ + +import java.awt.event.ActionEvent; +import javax.swing.AbstractAction; +import javax.swing.JMenu; +import javax.swing.JMenuItem; + +public class bug4148154 +{ + public static void main(String[] args) { + JMenu menu = new JMenu(); + JMenuItem mi = menu.add(new AbstractAction() { + public void actionPerformed(ActionEvent ev) {} + }); + if (mi.getHorizontalTextPosition() != JMenu.LEADING && + mi.getHorizontalTextPosition() != JMenu.TRAILING) { + + throw new RuntimeException("Failed:"); + } + } +} diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/NativeUtils.java b/test/jdk/javax/swing/JMenu/bug4156316.java similarity index 69% rename from test/hotspot/jtreg/vmTestbase/nsk/share/NativeUtils.java rename to test/jdk/javax/swing/JMenu/bug4156316.java index 4fb0db7675d..2d569903205 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/share/NativeUtils.java +++ b/test/jdk/javax/swing/JMenu/bug4156316.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2023, 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 @@ -20,12 +20,24 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package nsk.share; -public class NativeUtils { - static { - System.loadLibrary("native_utils"); +/* + * @test + * @bug 4156316 + * @summary checks if JMenu.add(Component) throws NullPointerException + * @run main bug4156316 + */ + +import javax.swing.JComponent; +import javax.swing.JMenu; + +public class bug4156316 { + + public static void main(String[] args) { + JMenu m = new JMenu("test"); + m.add(new XComponent()); } - public static native long getCurrentPID(); + static class XComponent extends JComponent { + } } diff --git a/test/jdk/javax/swing/JMenu/bug4161866.java b/test/jdk/javax/swing/JMenu/bug4161866.java new file mode 100644 index 00000000000..0363404e486 --- /dev/null +++ b/test/jdk/javax/swing/JMenu/bug4161866.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1999, 2023, 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 4161866 + * @summary Method AccessibleJMenu.removeAccessibleSelection does not + remove selections correctly + * @run main bug4161866 + */ + +import javax.accessibility.AccessibleSelection; +import javax.swing.JMenu; +import javax.swing.JMenuBar; + +public class bug4161866 { + + public static void main(String[] argv) { + JMenuBar mb = new JMenuBar(); + JMenu mnu = new JMenu(); + AccessibleSelection acs = mnu.getAccessibleContext(). + getAccessibleSelection(); + mb.add(mnu); + JMenu jm = new JMenu(); + mnu.add(jm); + jm.setSelected(true); + acs.addAccessibleSelection(0); + if (!jm.isSelected()) { + throw new RuntimeException("Selection should be non-empty..."); + } + + acs.removeAccessibleSelection(0); + if (jm.isSelected()) { + throw new RuntimeException("Selection still non-empty after " + + "it was removed"); + } + } +} diff --git a/test/jdk/javax/swing/JMenu/bug4244796.java b/test/jdk/javax/swing/JMenu/bug4244796.java new file mode 100644 index 00000000000..cbb6d66280c --- /dev/null +++ b/test/jdk/javax/swing/JMenu/bug4244796.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1999, 2023, 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 4244796 + * @summary Tests that JMenu has JMenu(Action) constructor + * @run main bug4244796 + */ + +import java.awt.event.ActionEvent; +import java.beans.PropertyChangeListener; +import javax.swing.Action; +import javax.swing.JMenu; + +public class bug4244796 { + + /** + * Auxilliary class implementing Action + */ + static class NullAction implements Action { + public void addPropertyChangeListener( + PropertyChangeListener listener) {} + public void removePropertyChangeListener( + PropertyChangeListener listener) {} + public void putValue(String key, Object value) {} + public void setEnabled(boolean b) {} + public void actionPerformed(ActionEvent e) {} + + public Object getValue(String key) { return null; } + public boolean isEnabled() { return false; } + } + + public static void main(String[] argv) { + Action action = new NullAction(); + JMenu menu = new JMenu(action); + } +} diff --git a/test/jdk/javax/swing/JMenu/bug4767393.java b/test/jdk/javax/swing/JMenu/bug4767393.java new file mode 100644 index 00000000000..617d50983f9 --- /dev/null +++ b/test/jdk/javax/swing/JMenu/bug4767393.java @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2003, 2023, 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 4767393 + * @summary Disabled JMenu is selectable via mnemonic + * @key headful + * @run main bug4767393 + */ + +import java.awt.Robot; +import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.SwingUtilities; + +public class bug4767393 { + + public static JFrame mainFrame; + public static JMenuBar menuBar; + public static JMenu menu; + public static JMenu disabled; + public static volatile boolean disabledMenuSelected = true; + + public static void main(String[] args) throws Exception { + try { + Robot robo = new Robot(); + robo.setAutoDelay(100); + SwingUtilities.invokeAndWait(() -> { + mainFrame = new JFrame("Bug4767393"); + menuBar = new JMenuBar(); + menu = new JMenu("File"); + disabled = new JMenu("Disabled"); + menuBar.add(menu); + menu.add("Menu Item 1"); + menu.add("Menu Item 2"); + disabled.setEnabled(false); + disabled.setMnemonic('D'); + disabled.add("Dummy menu item"); + menu.add(disabled); + menu.add("Menu Item 3"); + menu.add("Menu Item 4"); + mainFrame.setJMenuBar(menuBar); + + mainFrame.setSize(200, 200); + mainFrame.setLocationRelativeTo(null); + mainFrame.setVisible(true); + }); + robo.waitForIdle(); + robo.delay(500); + + robo.keyPress(KeyEvent.VK_F10); + robo.keyRelease(KeyEvent.VK_F10); + robo.keyPress(KeyEvent.VK_DOWN); + robo.keyRelease(KeyEvent.VK_DOWN); + robo.delay(500); + robo.keyPress(KeyEvent.VK_D); + robo.keyRelease(KeyEvent.VK_D); + robo.delay(100); + + SwingUtilities.invokeAndWait(() -> { + disabledMenuSelected = disabled.isSelected(); + }); + + if (disabledMenuSelected) { + throw new RuntimeException("Disabled JMenu is selected" + + " by the mnemonic. Test failed."); + } + } finally { + SwingUtilities.invokeAndWait(() -> { + if (mainFrame != null) { + mainFrame.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/JPopupMenu/6580930/bug6580930.java b/test/jdk/javax/swing/JPopupMenu/6580930/bug6580930.java index 05a78e48702..450ae0d74e9 100644 --- a/test/jdk/javax/swing/JPopupMenu/6580930/bug6580930.java +++ b/test/jdk/javax/swing/JPopupMenu/6580930/bug6580930.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,17 +24,26 @@ * @test * @key headful * @bug 6580930 7184956 + * @requires (os.family != "mac") * @summary Swing Popups should overlap taskbar - * @author Alexander Potochkin * @library ../../../../lib/testlibrary * @build ExtendedRobot * @run main bug6580930 */ -import javax.swing.*; -import java.awt.*; +import java.awt.Dimension; +import java.awt.Point; +import java.awt.Insets; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.Window; import java.awt.event.InputEvent; import java.awt.event.KeyEvent; +import javax.swing.JFrame; +import javax.swing.JMenuItem; +import javax.swing.JPanel; +import javax.swing.JPopupMenu; +import javax.swing.SwingUtilities; public class bug6580930 { private static ExtendedRobot robot; diff --git a/test/jdk/javax/swing/JRadioButton/bug4823809.java b/test/jdk/javax/swing/JRadioButton/bug4823809.java new file mode 100644 index 00000000000..810f4f42939 --- /dev/null +++ b/test/jdk/javax/swing/JRadioButton/bug4823809.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2003, 2023, 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.swing.JFrame; +import javax.swing.JRadioButton; +import javax.swing.SwingUtilities; +import javax.swing.plaf.ButtonUI; +import javax.swing.plaf.metal.MetalRadioButtonUI; +import java.awt.Dimension; +import java.awt.Graphics; +import java.awt.Rectangle; +import java.awt.Robot; + +/* + * @test + * @bug 4823809 + * @summary No Mnemonic or Focus Indicator when using HTML for a Component Text + * @key headful + * @run main bug4823809 + */ + +public class bug4823809 { + private static ButtonUI testUI; + private static volatile boolean passed = false; + private static JFrame frame; + private static Robot robot; + + public static void main(String[] args) throws Exception { + try { + robot = new Robot(); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("RadioButton Test"); + testUI = new TestRadioButtonUI(); + JRadioButton radio = new TestRadioButton("This is a radiobutton test!"); + + frame.getContentPane().add(radio); + frame.pack(); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + + if (!passed) { + throw new Error("Focus isn't painted for JRadioButton with HTML text."); + } + System.out.println("Test Passed!"); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static class TestRadioButton extends JRadioButton { + public TestRadioButton(String s) { + super(s); + } + + public void setUI(ButtonUI ui) { + super.setUI(testUI); + } + } + + static class TestRadioButtonUI extends MetalRadioButtonUI { + protected void paintFocus(Graphics g, Rectangle t, Dimension d) { + super.paintFocus(g, t, d); + passed = true; + } + } + +} diff --git a/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java b/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java index 560c5d82331..784cd00c244 100644 --- a/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java +++ b/test/jdk/javax/swing/JRootPane/DefaultButtonTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2023, 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 @@ -83,6 +83,7 @@ private void createUI() { public void runTest() throws Exception { Robot robot = new Robot(); + robot.setAutoWaitForIdle(true); robot.setAutoDelay(100); for (UIManager.LookAndFeelInfo laf : UIManager.getInstalledLookAndFeels()) { try { @@ -100,6 +101,8 @@ public void runTest() throws Exception { createUI(); }); robot.waitForIdle(); + robot.delay(1000); + robot.keyPress(KeyEvent.VK_ENTER); robot.keyRelease(KeyEvent.VK_ENTER); robot.waitForIdle(); diff --git a/test/jdk/javax/swing/JSpinner/8008657/bug8008657.java b/test/jdk/javax/swing/JSpinner/8008657/bug8008657.java index cbeb0c185bb..26ed0e0082c 100644 --- a/test/jdk/javax/swing/JSpinner/8008657/bug8008657.java +++ b/test/jdk/javax/swing/JSpinner/8008657/bug8008657.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2024, 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 @@ -39,7 +39,6 @@ * @test * @key headful * @bug 8008657 - * @author Alexander Scherbatiy * @summary JSpinner setComponentOrientation doesn't affect on text orientation * @run main bug8008657 */ @@ -137,6 +136,7 @@ static void createDateSpinner() { calendar.add(Calendar.YEAR, -1); Date earliestDate = calendar.getTime(); calendar.add(Calendar.YEAR, 1); + calendar.add(Calendar.DAY_OF_MONTH, 1); Date latestDate = calendar.getTime(); SpinnerModel dateModel = new SpinnerDateModel(initDate, earliestDate, diff --git a/test/jdk/javax/swing/JSplitPane/bug4147653.java b/test/jdk/javax/swing/JSplitPane/bug4147653.java new file mode 100644 index 00000000000..ed84776d46d --- /dev/null +++ b/test/jdk/javax/swing/JSplitPane/bug4147653.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 1999, 2023, 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.swing.JSplitPane; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +/* + * @test + * @bug 4147653 + * @summary JSplitPane.DIVIDER_LOCATION_PROPERTY is a property, + * you can use that to know when the position changes. + * @run main bug4147653 + */ + +public class bug4147653 { + private static volatile boolean flag = false; + + static class DevMoved implements PropertyChangeListener { + public void propertyChange(PropertyChangeEvent evt) { + flag = true; + } + } + + public static void main(String[] args) throws Exception { + JSplitPane sp = new JSplitPane(); + + DevMoved pl = new DevMoved(); + sp.addPropertyChangeListener(JSplitPane.DIVIDER_LOCATION_PROPERTY, pl); + sp.setDividerLocation(sp.getDividerLocation() + 10); + Thread.sleep(1000); + + if (!flag) { + throw new RuntimeException("Divider property was not changed..."); + } + System.out.println("Test Passed!"); + } +} diff --git a/test/jdk/javax/swing/JSplitPane/bug4870674.java b/test/jdk/javax/swing/JSplitPane/bug4870674.java new file mode 100644 index 00000000000..1984d747f76 --- /dev/null +++ b/test/jdk/javax/swing/JSplitPane/bug4870674.java @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2003, 2023, 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.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JSplitPane; +import javax.swing.SwingUtilities; +import javax.swing.plaf.basic.BasicSplitPaneDivider; +import javax.swing.plaf.basic.BasicSplitPaneUI; +import java.awt.GridLayout; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; + +/* + * @test + * @bug 4870674 + * @summary JSplitPane's one-touch buttons should deal with resized split panes better + * @key headful + * @run main bug4870674 + */ + +public class bug4870674 { + private static JSplitPane jsp0, jsp1; + private static JButton[] leftOneTouchButton = new JButton[2]; + private static JButton[] rightOneTouchButton = new JButton[2]; + private static JFrame frame; + private static Robot robot; + private static volatile boolean passed = true; + private static volatile Point rightBtnPos0; + private static volatile Point leftBtnPos0; + private static volatile Point rightBtnPos1; + private static volatile Point leftBtnPos1; + + public static void main(String[] args) throws Exception { + try { + robot = new Robot(); + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("Test"); + frame.getContentPane().setLayout(new GridLayout(2, 1)); + + jsp0 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, + new JButton("Left"), + new JButton("Right")); + frame.getContentPane().add(jsp0); + + jsp0.setUI(new TestSplitPaneUI(0)); + jsp0.setOneTouchExpandable(true); + + jsp1 = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, + new JButton("Left"), + new JButton("Right")); + frame.getContentPane().add(jsp1); + + jsp1.setUI(new TestSplitPaneUI(1)); + jsp1.setOneTouchExpandable(true); + + frame.setSize(300, 100); + frame.setVisible(true); + }); + robot.waitForIdle(); + robot.delay(1000); + SwingUtilities.invokeAndWait(() -> { + rightBtnPos0 = rightOneTouchButton[0].getLocationOnScreen(); + rightBtnPos0.x += rightOneTouchButton[0].getWidth() / 2; + rightBtnPos0.y += rightOneTouchButton[0].getHeight() / 2; + + leftBtnPos1 = leftOneTouchButton[1].getLocationOnScreen(); + leftBtnPos1.x += leftOneTouchButton[0].getWidth() / 2; + leftBtnPos1.y += leftOneTouchButton[0].getHeight() / 2; + + leftBtnPos0 = leftOneTouchButton[0].getLocationOnScreen(); + leftBtnPos0.x += leftOneTouchButton[0].getWidth() / 2; + leftBtnPos0.y += leftOneTouchButton[0].getHeight() / 2; + + rightBtnPos1 = rightOneTouchButton[1].getLocationOnScreen(); + rightBtnPos1.x += rightOneTouchButton[0].getWidth() / 2; + rightBtnPos1.y += rightOneTouchButton[0].getHeight() / 2; + + jsp0.setDividerLocation(250); + }); + robot.mouseMove(rightBtnPos0.x, rightBtnPos0.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + SwingUtilities.invokeAndWait(() -> { + jsp1.setDividerLocation(250); + }); + robot.waitForIdle(); + robot.delay(100); + robot.mouseMove(leftBtnPos1.x, leftBtnPos1.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + SwingUtilities.invokeAndWait(() -> { + frame.setSize(200, 100); + }); + robot.waitForIdle(); + robot.delay(100); + robot.mouseMove(leftBtnPos0.x, leftBtnPos0.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(100); + robot.mouseMove(rightBtnPos1.x, rightBtnPos1.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); + robot.delay(100); + + SwingUtilities.invokeAndWait(() -> { + if (jsp0.getDividerLocation() > jsp0.getMaximumDividerLocation() || + jsp1.getDividerLocation() > jsp1.getMaximumDividerLocation()) { + passed = false; + } + }); + + if (!passed) { + throw new RuntimeException("The divider location couldn't " + + "be greater then its maximum location"); + } + System.out.println("Test Passed!"); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + static class TestSplitPaneUI extends BasicSplitPaneUI { + int i; + + public TestSplitPaneUI(int i) { + super(); + this.i = i; + } + + public BasicSplitPaneDivider createDefaultDivider() { + return new TestSplitPaneDivider(this, i); + } + } + + static class TestSplitPaneDivider extends BasicSplitPaneDivider { + int i = 0; + + public TestSplitPaneDivider(BasicSplitPaneUI ui, int i) { + super(ui); + this.i = i; + } + + protected JButton createLeftOneTouchButton() { + leftOneTouchButton[i] = super.createLeftOneTouchButton(); + return leftOneTouchButton[i]; + } + + protected JButton createRightOneTouchButton() { + rightOneTouchButton[i] = super.createRightOneTouchButton(); + return rightOneTouchButton[i]; + } + } +} diff --git a/test/jdk/javax/swing/JTabbedPane/GetComponentAtTest.java b/test/jdk/javax/swing/JTabbedPane/GetComponentAtTest.java new file mode 100644 index 00000000000..ddefd541f40 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/GetComponentAtTest.java @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2000, 2023, 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 4122109 + * @summary Ensure SwingUtilities.getDeepestComponentAt() works correctly + * (in this particular case, with JTabbedPane) + * @key headful + * @run main GetComponentAtTest + */ + +import java.awt.BorderLayout; +import java.awt.Color; +import java.awt.Robot; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; + +public class GetComponentAtTest { + static JFrame f; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("GetComponentAtTest"); + JTabbedPane tabbedpane = new JTabbedPane(); + f.getContentPane().add(tabbedpane, BorderLayout.CENTER); + + JPanel panel1 = new JPanel(); + panel1.setName("Panel 1"); + panel1.setLayout(new BorderLayout()); + tabbedpane.add(panel1); + JPanel subPanel = new JPanel(); + subPanel.setName("Sub-Panel"); + subPanel.setBackground(Color.green); + panel1.add(subPanel); // add sub panel to 1st tab + + JPanel panel2 = new JPanel(); + panel2.setName("Panel 2"); + tabbedpane.add(panel2); + + f.setSize(150, 150); + f.setVisible(true); + + robot.delay(1000); + + tabbedpane.setSelectedIndex(1); // display 2nd tab + tabbedpane.invalidate(); + tabbedpane.validate(); + if (SwingUtilities.getDeepestComponentAt(tabbedpane, 50, 50) != panel2) { + throw new RuntimeException("SwingUtilities.getDeepestComponentAt() " + + "returned incorrect component! (1)"); + } + + tabbedpane.setSelectedIndex(0); // display 1st tab + tabbedpane.invalidate(); + tabbedpane.validate(); + if (SwingUtilities.getDeepestComponentAt(tabbedpane, 50, 50) != subPanel) { + throw new RuntimeException("SwingUtilities.getDeepestComponentAt() " + + "returned incorrect component! (2)"); + } + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + + } +} diff --git a/test/jdk/javax/swing/JTabbedPane/ReplaceCompTab.java b/test/jdk/javax/swing/JTabbedPane/ReplaceCompTab.java new file mode 100644 index 00000000000..92e9ffeff13 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/ReplaceCompTab.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 1999, 2023, 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 4213896 4228439 + * @summary Ensure that inserting a new tab with a component + * where that component already exists as another tab is handled + * properly. The old tab should be removed and the new tab added. + * @key headful + * @run main ReplaceCompTab + */ + +import java.awt.BorderLayout; + +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; + +public class ReplaceCompTab { + static JFrame f; + + public static void main(String[] args) throws Exception { + try { + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("ReplaceCompTab"); + JTabbedPane tabbedpane = new JTabbedPane(); + f.getContentPane().add(tabbedpane, BorderLayout.CENTER); + + JPanel comp = new JPanel(); + + // Add first tab + tabbedpane.addTab("First(temp)", comp); + + // Add second tab with same component (should just replace first one) + tabbedpane.insertTab("First", null, comp, "component added next", 0); + + // Check to ensure only a single tab exists + if (tabbedpane.getTabCount() > 1) { + throw new RuntimeException("Only one tab should exist"); + } + // Check to make sure second tab correctly replaced the first + if (!(tabbedpane.getTitleAt(0).equals("First"))) { + throw new RuntimeException("Tab not replaced correctly"); + } + // Check to make sure adding null continues to work + try { + tabbedpane.addTab("Second", null); + } catch (Exception e) { + throw new RuntimeException("Adding first null " + + "component failed:", e); + } + try { + tabbedpane.addTab("Third", null); + } catch (Exception e) { + throw new RuntimeException("Adding subsequent null " + + "component failed: ", e); + } + try { + tabbedpane.setComponentAt(1, new JLabel("Second Component")); + tabbedpane.setComponentAt(2, new JLabel("Third Component")); + } catch (Exception e) { + throw new RuntimeException("Setting null component " + + "to non-null failed: ", e); + } + }); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + } +} diff --git a/test/jdk/javax/swing/JTabbedPane/bug4703690.java b/test/jdk/javax/swing/JTabbedPane/bug4703690.java new file mode 100644 index 00000000000..08be30def82 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/bug4703690.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2003, 2023, 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 4703690 + * @summary JTabbedPane should focus proper component at the tab container + * @key headful + * @run main bug4703690 + */ + +import java.awt.Point; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.InputEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; + +public class bug4703690 { + static JFrame frame; + static JTabbedPane tabbedPane; + static JButton one, two; + + static final CountDownLatch focusButtonTwo = new CountDownLatch(1); + static final CountDownLatch switchToTabTwo = new CountDownLatch(1); + static final CountDownLatch focusButtonOne = new CountDownLatch(1); + static Robot robot; + + static Point p; + static Rectangle rect; + + public static void main(String[] args) throws Exception { + bug4703690 test = new bug4703690(); + try { + SwingUtilities.invokeAndWait(() -> { + frame = new JFrame("bug4703690"); + + JPanel panel = new JPanel(); + one = new JButton("Button 1"); + panel.add(one); + two = new JButton("Button 2"); + panel.add(two); + + tabbedPane = new JTabbedPane(); + frame.getContentPane().add(tabbedPane); + tabbedPane.addTab("Tab one", panel); + tabbedPane.addTab("Tab two", new JPanel()); + + two.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + focusButtonTwo.countDown(); + } + }); + + tabbedPane.addChangeListener(e -> { + if (tabbedPane.getSelectedIndex() == 1) { + switchToTabTwo.countDown(); + } + }); + + frame.setSize(200, 200); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + }); + + test.execute(); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (frame != null) { + frame.dispose(); + } + }); + } + } + + public void execute() throws Exception { + robot = new Robot(); + robot.setAutoDelay(50); + + SwingUtilities.invokeAndWait(two::requestFocus); + + if (!focusButtonTwo.await(1, TimeUnit.SECONDS)) { + throw new RuntimeException("Button two didn't receive focus"); + } + + one.addFocusListener(new FocusAdapter() { + public void focusGained(FocusEvent e) { + focusButtonOne.countDown(); + } + }); + + // Switch to tab two + SwingUtilities.invokeAndWait(() -> { + p = tabbedPane.getLocationOnScreen(); + rect = tabbedPane.getBoundsAt(1); + }); + robot.mouseMove(p.x + rect.x + rect.width / 2, + p.y + rect.y + rect.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + if (!switchToTabTwo.await(1, TimeUnit.SECONDS)) { + throw new RuntimeException("Switching to tab two failed"); + } + + // Switch to tab one + SwingUtilities.invokeAndWait(() -> { + p = tabbedPane.getLocationOnScreen(); + rect = tabbedPane.getBoundsAt(0); + }); + robot.mouseMove(p.x + rect.x + rect.width / 2, + p.y + rect.y + rect.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + if (!focusButtonOne.await(1, TimeUnit.SECONDS)) { + throw new RuntimeException("The 'Button 1' button doesn't have focus"); + } + } +} diff --git a/test/jdk/javax/swing/JTextArea/bug4849868.java b/test/jdk/javax/swing/JTextArea/bug4849868.java new file mode 100644 index 00000000000..efd94b46336 --- /dev/null +++ b/test/jdk/javax/swing/JTextArea/bug4849868.java @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2003, 2023, 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 4849868 + * @summary Tests if JTextArea.getSelectionEnd works correctly + * @key headful + * @run main bug4849868 + */ + +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.InputEvent; + +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +public class bug4849868 { + + private static volatile boolean passed = false; + + private static JTextArea textArea; + private static JFrame f; + private static Point p; + + private static int end; + private static int len; + + public static void main(String[] args) throws Exception { + try { + Robot robot = new Robot(); + robot.setAutoDelay(100); + robot.setAutoWaitForIdle(true); + + SwingUtilities.invokeAndWait(() -> { + f = new JFrame("bug4849868"); + textArea = new JTextArea("1234"); + textArea.setLineWrap(true); + JScrollPane pane = new JScrollPane(textArea, + JScrollPane.VERTICAL_SCROLLBAR_ALWAYS, + JScrollPane.HORIZONTAL_SCROLLBAR_NEVER); + f.getContentPane().add(pane); + f.setSize(300, 300); + f.setLocationRelativeTo(null); + f.setVisible(true); + }); + + robot.waitForIdle(); + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> + p = textArea.getLocationOnScreen()); + + robot.mouseMove(p.x, p.y); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseMove(p.x + 350, p.y); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.delay(1000); + + SwingUtilities.invokeAndWait(() -> { + end = textArea.getSelectionEnd(); + len = textArea.getDocument().getLength(); + }); + passed = (end <= len); + + System.out.println("end: " + end); + System.out.println("len: " + len); + } finally { + SwingUtilities.invokeAndWait(() -> { + if (f != null) { + f.dispose(); + } + }); + } + + if (!passed) { + throw new RuntimeException("Test failed."); + } + } +} diff --git a/test/jdk/javax/swing/JTextField/bug4244613.java b/test/jdk/javax/swing/JTextField/bug4244613.java new file mode 100644 index 00000000000..6a1a8bb9d23 --- /dev/null +++ b/test/jdk/javax/swing/JTextField/bug4244613.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 1999, 2023, 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 4244613 + * @summary Tests that JTextField has setAction(Action) constructor + * @run main bug4244613 + */ + +import java.awt.event.ActionEvent; + +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.JTextField; + +public class bug4244613 { + /** Auxilliary class implementing Action + */ + static class NullAction extends AbstractAction { + @Override + public void actionPerformed(ActionEvent e) {} + public Object getValue(String key) { return null; } + public boolean isEnabled() { return false; } + } + + public static void main(String[] args) { + JTextField tf = new JTextField("bug4244613"); + Action action = new NullAction(); + tf.setAction(action); + } +} diff --git a/test/jdk/javax/swing/JToolBar/bug4203039.java b/test/jdk/javax/swing/JToolBar/bug4203039.java new file mode 100644 index 00000000000..6c25bb505ea --- /dev/null +++ b/test/jdk/javax/swing/JToolBar/bug4203039.java @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2003, 2023, 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.awt.BorderLayout; + +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JToolBar; +import javax.swing.SwingUtilities; + +/* + * @test + * @bug 4203039 + * @summary JToolBar needs a way to limit docking to a particular orientation + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4203039 + */ + +public class bug4203039 { + private static final String instructionsText = "This test is used to verify that application-installed\n" + + "components prevent the toolbar from docking in\n" + + "those locations.\n\n" + + + "This test has installed components on the SOUTH\n" + + "and EAST, so verify the toolbar cannot dock in those\n" + + "locations but can dock on the NORTH and WEST"; + + public static void main(String[] args) throws Exception { + PassFailJFrame passFailJFrame = new PassFailJFrame.Builder() + .title("bug4203039 Instructions") + .instructions(instructionsText) + .testTimeOut(5) + .rows(10) + .columns(35) + .build(); + + SwingUtilities.invokeAndWait(() -> { + JFrame frame = new JFrame("bug4203039"); + frame.setSize(300, 200); + + JToolBar toolbar = new JToolBar(); + JLabel label = new JLabel("This is the toolbar"); + toolbar.add(label); + + frame.add(toolbar, BorderLayout.NORTH); + + frame.add(new JComponent(){}, BorderLayout.SOUTH); + frame.add(new JComponent(){}, BorderLayout.EAST); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, + PassFailJFrame.Position.HORIZONTAL); + + frame.setVisible(true); + }); + + passFailJFrame.awaitAndCheck(); + } +} diff --git a/test/jdk/javax/swing/JTree/8003400/Test8003400.java b/test/jdk/javax/swing/JTree/8003400/Test8003400.java index 95f5e826aa9..dcc9b0fce6e 100644 --- a/test/jdk/javax/swing/JTree/8003400/Test8003400.java +++ b/test/jdk/javax/swing/JTree/8003400/Test8003400.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2023, 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 @@ -109,6 +109,10 @@ public void run() { Robot robot = new Robot(); robot.setAutoDelay(100); + robot.setAutoWaitForIdle(true); + robot.waitForIdle(); + robot.delay(500); + SwingUtilities.invokeAndWait(() -> { point = tree.getLocationOnScreen(); rect = tree.getBounds(); diff --git a/test/jdk/javax/swing/border/Test4129681.html b/test/jdk/javax/swing/border/Test4129681.html deleted file mode 100644 index c80b417075a..00000000000 --- a/test/jdk/javax/swing/border/Test4129681.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - -When applet starts, you'll see a checkbox and a label with a titled border. -Turn on the checkbox to disable the label. -The test passes if the title of the border is disabled as well as the label. - - - - - diff --git a/test/jdk/javax/swing/border/Test4129681.java b/test/jdk/javax/swing/border/Test4129681.java index 330126d3f3f..993dc2d139c 100644 --- a/test/jdk/javax/swing/border/Test4129681.java +++ b/test/jdk/javax/swing/border/Test4129681.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2024, 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 @@ -21,39 +21,62 @@ * questions. */ +import java.awt.Color; +import java.awt.Dimension; +import java.awt.Graphics2D; +import java.awt.Point; +import javax.swing.BorderFactory; +import javax.swing.JLabel; +import javax.swing.UIManager; + +import javax.imageio.ImageIO; +import java.awt.image.BufferedImage; +import java.io.File; + /* * @test * @bug 4129681 - * @summary Tests enabling/disabling of titled border's caption - * @author Sergey Malenkov - * @run applet/manual=yesno Test4129681.html + * @summary Tests disabling of titled border's caption + * @run main/othervm -Dsun.java2d.uiScale=1 Test4129681 */ -import java.awt.BorderLayout; -import java.awt.event.ItemEvent; -import java.awt.event.ItemListener; -import javax.swing.BorderFactory; -import javax.swing.JApplet; -import javax.swing.JCheckBox; -import javax.swing.JLabel; +public class Test4129681 { + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + int correctColoredPixels = 0; + int totalPixels = 0; + int tolerance = 20; + JLabel label; + Color labelDisableColor = Color.RED; + Dimension SIZE = new Dimension(100, 40); + Point startPoint = new Point(8, 4); + Point endPoint = new Point(18, 14); -public class Test4129681 extends JApplet implements ItemListener { - private JLabel label; + label = new JLabel("Label"); + label.setBorder(BorderFactory.createTitledBorder("\u2588".repeat(5))); + UIManager.getDefaults().put("Label.disabledForeground", labelDisableColor); + label.setSize(SIZE); + label.setEnabled(false); + BufferedImage image = new BufferedImage(label.getWidth(), label.getHeight(), + BufferedImage.TYPE_INT_ARGB); - @Override - public void init() { - JCheckBox check = new JCheckBox("disable"); - check.addItemListener(this); + Graphics2D g2d = image.createGraphics(); + label.paint(g2d); + g2d.dispose(); - this.label = new JLabel("message"); - this.label.setBorder(BorderFactory.createTitledBorder("label")); - this.label.setEnabled(!check.isSelected()); - - add(BorderLayout.NORTH, check); - add(BorderLayout.CENTER, this.label); - } + for (int x = startPoint.x; x < endPoint.x; x++) { + for (int y = startPoint.y; y < endPoint.y; y++) { + if (image.getRGB(x, y) == labelDisableColor.getRGB()) { + correctColoredPixels++; + } + totalPixels++; + } + } - public void itemStateChanged(ItemEvent event) { - this.label.setEnabled(ItemEvent.DESELECTED == event.getStateChange()); + if (((double) correctColoredPixels / totalPixels * 100) <= tolerance) { + ImageIO.write(image, "png", new File("failureImage.png")); + throw new RuntimeException("Label with border is not disabled"); + } + System.out.println("Test Passed"); } } diff --git a/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/ConcurrentModification.java b/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/ConcurrentModification.java new file mode 100644 index 00000000000..e5db49b46ec --- /dev/null +++ b/test/jdk/javax/swing/plaf/basic/BasicDirectoryModel/ConcurrentModification.java @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2024, 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.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; +import java.util.Timer; +import java.util.TimerTask; +import java.util.concurrent.BrokenBarrierException; +import java.util.concurrent.CyclicBarrier; +import java.util.concurrent.atomic.AtomicReference; +import java.util.stream.IntStream; +import java.util.stream.LongStream; + +import javax.swing.JFileChooser; + +/* + * @test + * @bug 8323670 8307091 8240690 + * @requires os.family == "mac" | os.family == "linux" + * @summary Verifies thread-safety of BasicDirectoryModel (JFileChooser) + * @run main/othervm -Djava.awt.headless=true ConcurrentModification + */ +public final class ConcurrentModification extends ThreadGroup { + /** Initial number of files. */ + private static final long NUMBER_OF_FILES = 50; + /** Maximum number of files created on a timer tick. */ + private static final long LIMIT_FILES = 10; + + /** Timer period (delay) for creating new files. */ + private static final long TIMER_PERIOD = 250; + + /** + * Number of threads running {@code fileChooser.rescanCurrentDirectory()}. + */ + private static final int NUMBER_OF_THREADS = 5; + /** Number of repeated calls to {@code rescanCurrentDirectory}. */ + private static final int NUMBER_OF_REPEATS = 2_000; + /** Maximum amount a thread waits before initiating rescan. */ + private static final long LIMIT_SLEEP = 100; + + + /** The barrier to start all the scanner threads simultaneously. */ + private static final CyclicBarrier start = new CyclicBarrier(NUMBER_OF_THREADS); + /** The barrier to wait for all the scanner threads to complete, plus main thread. */ + private static final CyclicBarrier end = new CyclicBarrier(NUMBER_OF_THREADS + 1); + + /** List of scanner threads. */ + private static final List threads = new ArrayList<>(NUMBER_OF_THREADS); + + /** + * Stores an exception caught by any of the threads. + * If more exceptions are caught, they're added as suppressed exceptions. + */ + private static final AtomicReference exception = + new AtomicReference<>(); + + /** + * Stores an {@code IOException} thrown while removing the files. + */ + private static final AtomicReference ioException = + new AtomicReference<>(); + + + public static void main(String[] args) throws Throwable { + try { + // Start the test in its own thread group to catch and handle + // all thrown exceptions, in particular in + // BasicDirectoryModel.FilesLoader which is created by Swing. + ThreadGroup threadGroup = new ConcurrentModification(); + Thread runner = new Thread(threadGroup, + ConcurrentModification::wrapper, + "Test Runner"); + runner.start(); + runner.join(); + } catch (Throwable throwable) { + handleException(throwable); + } + + if (ioException.get() != null) { + System.err.println("An error occurred while removing files:"); + ioException.get().printStackTrace(); + } + + if (exception.get() != null) { + throw exception.get(); + } + } + + private static void wrapper() { + final long timeStart = System.currentTimeMillis(); + try { + runTest(timeStart); + } catch (Throwable throwable) { + handleException(throwable); + } finally { + System.out.printf("Duration: %,d\n", + (System.currentTimeMillis() - timeStart)); + } + } + + private static void runTest(final long timeStart) throws Throwable { + final Path temp = Files.createDirectory(Paths.get("fileChooser-concurrency-" + timeStart)); + + final Timer timer = new Timer("File creator"); + + try { + createFiles(temp); + + final JFileChooser fc = new JFileChooser(temp.toFile()); + + IntStream.range(0, NUMBER_OF_THREADS) + .forEach(i -> { + Thread thread = new Thread(new Scanner(fc)); + threads.add(thread); + thread.start(); + }); + + timer.scheduleAtFixedRate(new CreateFilesTimerTask(temp), + 0, TIMER_PERIOD); + + end.await(); + } catch (Throwable e) { + threads.forEach(Thread::interrupt); + throw e; + } finally { + timer.cancel(); + + deleteFiles(temp); + deleteFile(temp); + } + } + + + private ConcurrentModification() { + super("bdmConcurrency"); + } + + @Override + public void uncaughtException(Thread t, Throwable e) { + handleException(t, e); + } + + private static void handleException(Throwable throwable) { + handleException(Thread.currentThread(), throwable); + } + + private static void handleException(final Thread thread, + final Throwable throwable) { + System.err.println("Exception in " + thread.getName() + ": " + + throwable.getClass() + + (throwable.getMessage() != null + ? ": " + throwable.getMessage() + : "")); + if (!exception.compareAndSet(null, throwable)) { + exception.get().addSuppressed(throwable); + } + threads.stream() + .filter(t -> t != thread) + .forEach(Thread::interrupt); + } + + + private static class Scanner implements Runnable { + + private JFileChooser fileChooser; + + private Scanner(JFileChooser fileChooser) { + this.fileChooser = fileChooser; + } + + @Override + public void run() { + try { + start.await(); + + int counter = 0; + try { + do { + fileChooser.rescanCurrentDirectory(); + Thread.sleep((long) (Math.random() * LIMIT_SLEEP)); + } while (++counter < NUMBER_OF_REPEATS + && !Thread.interrupted()); + } catch (InterruptedException e) { + // Just exit the loop + } + } catch (Throwable throwable) { + handleException(throwable); + } finally { + try { + end.await(); + } catch (InterruptedException | BrokenBarrierException e) { + handleException(e); + } + } + } + } + + private static void createFiles(final Path parent) { + createFiles(parent, 0, NUMBER_OF_FILES); + } + + private static void createFiles(final Path parent, + final long start, + final long end) { + LongStream.range(start, end) + .forEach(n -> createFile(parent.resolve(n + ".file"))); + } + + private static void createFile(final Path file) { + try { + Files.createFile(file); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private static void deleteFiles(final Path parent) throws IOException { + try (var stream = Files.walk(parent)) { + stream.filter(p -> p != parent) + .forEach(ConcurrentModification::deleteFile); + } + } + + private static void deleteFile(final Path file) { + try { + Files.delete(file); + } catch (IOException e) { + if (!ioException.compareAndSet(null, e)) { + ioException.get().addSuppressed(e); + } + } + } + + private static final class CreateFilesTimerTask extends TimerTask { + private final Path temp; + private long no; + + public CreateFilesTimerTask(Path temp) { + this.temp = temp; + no = NUMBER_OF_FILES; + } + + @Override + public void run() { + try { + long count = (long) (Math.random() * LIMIT_FILES); + createFiles(temp, no, no + count); + no += count; + } catch (Throwable t) { + handleException(t); + } + } + } +} diff --git a/test/jdk/javax/swing/text/PaintTest.java b/test/jdk/javax/swing/text/PaintTest.java new file mode 100644 index 00000000000..a980d36c16d --- /dev/null +++ b/test/jdk/javax/swing/text/PaintTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 1999, 2024, 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 4210250 + * @summary Tests that PlainView repaints the necessary lines of text. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual PaintTest + */ + +import java.awt.Container; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.Rectangle; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JScrollPane; +import javax.swing.JTextArea; +import javax.swing.SwingUtilities; + +public class PaintTest { + + private static final String INSTRUCTIONS = + "Click the paint button.\n" + + "If half of the second line is erased,\n" + + "that is you can only see the bottom half of the second line\n" + + "with the top half painted over in white, click fail, else click pass."; + + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("PlainView Repaint Instructions") + .instructions(INSTRUCTIONS) + .rows(7) + .columns(35) + .testUI(PaintTest::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + JFrame frame = new JFrame("PaintTest"); + + new PaintTest().create(frame.getContentPane()); + frame.pack(); + return frame; + } + + + void create(Container parent) { + parent.setLayout(new FlowLayout()); + + final JTextArea ta = new JTextArea + ("A sample textarea\nwith a couple of lines\nof text") { + public Dimension getPreferredSize() { + Dimension size = super.getPreferredSize(); + if (getFont() != null) { + size.height += getFontMetrics(getFont()) + .getHeight() / 2; + } + return size; + } + }; + JButton button = new JButton("paint"); + + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent ae) { + SwingUtilities.invokeLater(new Runnable() { + public void run() { + Rectangle taBounds = ta.getBounds(); + int fontHeight = + ta.getFontMetrics(ta.getFont()).getHeight(); + + taBounds.height = fontHeight + fontHeight / 2; + ta.repaint(taBounds); + } + }); + } + }); + + parent.add(new JScrollPane(ta)); + parent.add(button); + } +} diff --git a/test/jdk/javax/swing/text/bug4148489.java b/test/jdk/javax/swing/text/bug4148489.java new file mode 100644 index 00000000000..74d8c28b2fe --- /dev/null +++ b/test/jdk/javax/swing/text/bug4148489.java @@ -0,0 +1,109 @@ +/* + * Copyright (c) 1999, 2024, 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 4148489 + * @summary Text gets deleted with negative values for setFirstLineIndent. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4148489 + */ + +import java.awt.BorderLayout; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTextPane; +import javax.swing.UIManager; +import javax.swing.text.BadLocationException; +import javax.swing.text.DefaultStyledDocument; +import javax.swing.text.JTextComponent; +import javax.swing.text.StyleConstants; +import javax.swing.text.StyleContext; +import javax.swing.text.Style; + +public class bug4148489 { + + static StyleContext sc; + static DefaultStyledDocument doc; + + private static final String INSTRUCTIONS = + "Put the cursor at the beginning of the first text line and move the\n" + + "cursor to the right using arrow key.\n" + + "If the text is not corrupted then click Pass\n" + + "If the text disappear while cursor moves click Fail."; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("Text traversal Instructions") + .instructions(INSTRUCTIONS) + .rows(5) + .columns(35) + .testUI(bug4148489::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + try { + UIManager.setLookAndFeel(UIManager.getCrossPlatformLookAndFeelClassName()); + } catch (Exception e) { + System.err.println("Error loading L&F: " + e); + } + JPanel testPanel = new JPanel(); + testPanel.setLayout(new BorderLayout()); + sc = new StyleContext(); + doc = new DefaultStyledDocument(sc); + + setParagraph(); + JTextComponent editor = new JTextPane(doc); + JScrollPane scroller = new JScrollPane(); + scroller.getViewport().add(editor); + JPanel panel = new JPanel(); + panel.setLayout(new BorderLayout()); + panel.add("Center", scroller); + testPanel.add("Center", panel); + JFrame frame = new JFrame("Styled Document"); + frame.add(testPanel); + frame.pack(); + return frame; + } + + static void setParagraph() { + Style sty = sc.addStyle("normal", sc.getStyle(StyleContext.DEFAULT_STYLE)); + //here sets the negative value for setFirstLineIndent + StyleConstants.setFirstLineIndent(sty, -50); + StyleConstants.setLeftIndent(sty, 50); + String data = "Here I wrote some text for test. You can ignore this text because of it's a senseless text."; + try { + Style s = null; + doc.insertString(doc.getLength(), data, s); + Style ls = sc.getStyle("normal"); + doc.setLogicalStyle(doc.getLength() - 1, ls); + doc.insertString(doc.getLength(), "\n", null); + } catch (BadLocationException e) { + throw new RuntimeException("BadLocationException occures while calls insertString()...", e); + } + } +} diff --git a/test/jdk/javax/swing/text/html/StyleSheet/bug4803145.java b/test/jdk/javax/swing/text/html/StyleSheet/bug4803145.java new file mode 100644 index 00000000000..9a9b9fdec1a --- /dev/null +++ b/test/jdk/javax/swing/text/html/StyleSheet/bug4803145.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2003, 2024, 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 4803145 + * @summary Tests if bullets for HTML
      are on the correct side for Arabic and Hebrew in JEditorPane + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual bug4803145 +*/ + +import java.awt.BorderLayout; +import java.awt.ComponentOrientation; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JEditorPane; +import javax.swing.JFrame; +import javax.swing.text.html.HTMLEditorKit; + +public class bug4803145 { + + private static final String INSTRUCTIONS = + "A JEditorPane with some html list in Hebrew appears.\n" + + "The bullets should be on the left side of the list items.\n" + + "Press the \"switch text orientation\" button.\n" + + "After the text relayouts:\n" + + "- If the bullets are to the right of the list items then test PASSED.\n" + + "- If the bullets remained on the left side then test FAILED."; + + public static void main(String[] args) throws Exception { + PassFailJFrame.builder() + .title("JEditorPane Instructions") + .instructions(INSTRUCTIONS) + .rows(10) + .columns(30) + .testUI(bug4803145::createTestUI) + .build() + .awaitAndCheck(); + } + + private static JFrame createTestUI() { + + String text = + "
        " + + "
      • מבוא" + + "
      • אחסון" + + "
      • (new code) הקוד הישן (Old Code)" + + "
      "; + + JFrame f = new JFrame("bug4803145"); + JEditorPane jep = new JEditorPane(); + jep.setEditorKit(new HTMLEditorKit()); + jep.setEditable(false); + + jep.setText(text); + + f.setSize(500, 500); + f.add(jep); + + JButton switchButton = new JButton("switch text orientation"); + switchButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + boolean isLeftToRight = jep.getComponentOrientation().isLeftToRight(); + jep.setComponentOrientation(isLeftToRight ? ComponentOrientation.RIGHT_TO_LEFT : + ComponentOrientation.LEFT_TO_RIGHT); + } + }); + f.add(switchButton, BorderLayout.SOUTH); + f.pack(); + return f; + } + +} diff --git a/test/jdk/javax/xml/crypto/dsig/GenerationTests.java b/test/jdk/javax/xml/crypto/dsig/GenerationTests.java index 862e9416793..971264b6d57 100644 --- a/test/jdk/javax/xml/crypto/dsig/GenerationTests.java +++ b/test/jdk/javax/xml/crypto/dsig/GenerationTests.java @@ -352,7 +352,7 @@ public static void main(String args[]) throws Exception { try (Http server = Http.startServer()) { server.start(); - // tests for XML documents + System.out.println("\ntests for XML documents"); Arrays.stream(canonicalizationMethods).forEach(c -> Arrays.stream(allSignatureMethods).forEach(s -> Arrays.stream(allDigestMethods).forEach(d -> @@ -366,7 +366,7 @@ public static void main(String args[]) throws Exception { } }))))); - // tests for text data with no transform + System.out.println("\ntests for text data with no transform"); Arrays.stream(canonicalizationMethods).forEach(c -> Arrays.stream(allSignatureMethods).forEach(s -> Arrays.stream(allDigestMethods).forEach(d -> @@ -379,7 +379,7 @@ public static void main(String args[]) throws Exception { } })))); - // tests for base64 data + System.out.println("\ntests for base64 data"); Arrays.stream(canonicalizationMethods).forEach(c -> Arrays.stream(allSignatureMethods).forEach(s -> Arrays.stream(allDigestMethods).forEach(d -> @@ -396,7 +396,7 @@ public static void main(String args[]) throws Exception { // negative tests - // unknown CanonicalizationMethod + System.out.println("\nunknown CanonicalizationMethod"); test_create_detached_signature( CanonicalizationMethod.EXCLUSIVE + BOGUS, SignatureMethod.DSA_SHA1, @@ -408,7 +408,7 @@ public static void main(String args[]) throws Exception { true, NoSuchAlgorithmException.class); - // unknown SignatureMethod + System.out.println("\nunknown SignatureMethod"); test_create_detached_signature( CanonicalizationMethod.EXCLUSIVE, SignatureMethod.DSA_SHA1 + BOGUS, @@ -419,7 +419,7 @@ public static void main(String args[]) throws Exception { true, NoSuchAlgorithmException.class); - // unknown DigestMethod + System.out.println("\nunknown DigestMethod"); test_create_detached_signature( CanonicalizationMethod.EXCLUSIVE, SignatureMethod.DSA_SHA1, @@ -430,7 +430,7 @@ public static void main(String args[]) throws Exception { true, NoSuchAlgorithmException.class); - // unknown Transform + System.out.println("\nunknown Transform"); test_create_detached_signature( CanonicalizationMethod.EXCLUSIVE, SignatureMethod.DSA_SHA1, @@ -441,7 +441,7 @@ public static void main(String args[]) throws Exception { true, NoSuchAlgorithmException.class); - // no source document + System.out.println("\nno source document"); test_create_detached_signature( CanonicalizationMethod.EXCLUSIVE, SignatureMethod.DSA_SHA1, @@ -453,7 +453,7 @@ public static void main(String args[]) throws Exception { true, XMLSignatureException.class); - // wrong transform for text data + System.out.println("\nwrong transform for text data"); test_create_detached_signature( CanonicalizationMethod.EXCLUSIVE, SignatureMethod.DSA_SHA1, @@ -1823,6 +1823,7 @@ static boolean test_create_detached_signature0(String canonicalizationMethod, throws Exception { System.out.print("-S"); + System.out.flush(); DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setNamespaceAware(true); @@ -1907,6 +1908,7 @@ static boolean test_create_detached_signature0(String canonicalizationMethod, } System.out.print("V"); + System.out.flush(); try (ByteArrayInputStream bis = new ByteArrayInputStream( signatureString.getBytes())) { doc = dbf.newDocumentBuilder().parse(bis); @@ -1930,12 +1932,14 @@ static boolean test_create_detached_signature0(String canonicalizationMethod, boolean success = signature.validate(vc); if (!success) { System.out.print("x"); + System.out.flush(); return false; } success = signature.getSignatureValue().validate(vc); if (!success) { System.out.print("X"); + System.out.flush(); return false; } diff --git a/test/jdk/jdk/jfr/event/oldobject/TestSanityDefault.java b/test/jdk/jdk/jfr/event/oldobject/TestSanityDefault.java index 10c26c69ff1..c2ddc21abc4 100644 --- a/test/jdk/jdk/jfr/event/oldobject/TestSanityDefault.java +++ b/test/jdk/jdk/jfr/event/oldobject/TestSanityDefault.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -40,7 +40,7 @@ * @requires vm.gc == "null" * @library /test/lib /test/jdk * @summary Purpose of this test is to run leak profiler without command line tweaks or WhiteBox hacks until we succeed - * @run main/othervm jdk.jfr.event.oldobject.TestSanityDefault + * @run main/othervm -Xmx1G jdk.jfr.event.oldobject.TestSanityDefault */ public class TestSanityDefault { diff --git a/test/jdk/jdk/security/logging/RecursiveEventHelper.java b/test/jdk/jdk/security/logging/RecursiveEventHelper.java new file mode 100644 index 00000000000..936d01f8115 --- /dev/null +++ b/test/jdk/jdk/security/logging/RecursiveEventHelper.java @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2024, 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.logging.*; + +import jdk.internal.event.EventHelper; + +/* + * @test + * @bug 8329013 + * @summary StackOverflowError when starting Apache Tomcat with signed jar + * @modules java.base/jdk.internal.event:+open + * @run main/othervm -Xmx32m -Djava.util.logging.manager=RecursiveEventHelper RecursiveEventHelper + */ +public class RecursiveEventHelper extends LogManager { + // an extra check to ensure the custom manager is in use + static volatile boolean customMethodCalled; + + public static void main(String[] args) throws Exception { + String classname = System.getProperty("java.util.logging.manager"); + if (!classname.equals("RecursiveEventHelper")) { + throw new RuntimeException("java.util.logging.manager not set"); + } + + // this call will trigger initialization of logging framework + // which will call into our custom LogManager and use the + // custom getProperty method below. EventHelper.isLoggingSecurity() + // is also on the code path of original report and triggers + // similar recursion. + System.getLogger("testLogger"); + if (!customMethodCalled) { + throw new RuntimeException("Method not called"); + } + } + + @Override + public String getProperty(String p) { + // this call mimics issue reported in initial bug report where + // opening of a signed jar during System logger initialization triggered + // a recursive call (via EventHelper.isLoggingSecurity) back into + // logger API + EventHelper.isLoggingSecurity(); + customMethodCalled = true; + return super.getProperty(p); + } +} diff --git a/test/jdk/lib/testlibrary/java/util/jar/JarBuilder.java b/test/jdk/lib/testlibrary/java/util/jar/JarBuilder.java index 7f7449a8344..ebe349ec780 100644 --- a/test/jdk/lib/testlibrary/java/util/jar/JarBuilder.java +++ b/test/jdk/lib/testlibrary/java/util/jar/JarBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it diff --git a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java index 32fba48cc3d..33f777d6490 100644 --- a/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java +++ b/test/jdk/security/infra/java/security/cert/CertPathValidator/certification/CAInterop.java @@ -483,6 +483,28 @@ * @run main/othervm/manual -Djava.security.debug=certpath CAInterop globalsigne46 CRL */ +/* + * @test id=ssltlsrootecc2022 + * @bug 8341057 + * @summary Interoperability tests with SSL TLS 2022 root CAs + * @library /test/lib + * @build jtreg.SkippedException ValidatePathWithURL CAInterop + * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop ssltlsrootecc2022 DEFAULT + * @run main/othervm/manual -Djava.security.debug=certpath,ocsp -Dcom.sun.security.ocsp.useget=false CAInterop ssltlsrootecc2022 DEFAULT + * @run main/othervm/manual -Djava.security.debug=certpath CAInterop ssltlsrootecc2022 CRL + */ + +/* + * @test id=ssltlsrootrsa2022 + * @bug 8341057 + * @summary Interoperability tests with SSL TLS 2022 root CAs + * @library /test/lib + * @build jtreg.SkippedException ValidatePathWithURL CAInterop + * @run main/othervm/manual -Djava.security.debug=certpath,ocsp CAInterop ssltlsrootrsa2022 DEFAULT + * @run main/othervm/manual -Djava.security.debug=certpath,ocsp -Dcom.sun.security.ocsp.useget=false CAInterop ssltlsrootrsa2022 DEFAULT + * @run main/othervm/manual -Djava.security.debug=certpath CAInterop ssltlsrootrsa2022 CRL + */ + /** * Collection of certificate validation tests for interoperability with external CAs. * These tests are marked as manual as they depend on external infrastructure and may fail @@ -661,6 +683,13 @@ private CATestURLs getTestURLs(String alias) { return new CATestURLs("https://valid.e46.roots.globalsign.com", "https://revoked.e46.roots.globalsign.com"); + case "ssltlsrootecc2022": + return new CATestURLs("https://test-root-2022-ecc.ssl.com", + "https://revoked-root-2022-ecc.ssl.com"); + case "ssltlsrootrsa2022": + return new CATestURLs("https://test-root-2022-rsa.ssl.com", + "https://revoked-root-2022-rsa.ssl.com"); + default: throw new RuntimeException("No test setup found for: " + alias); } } diff --git a/test/jdk/sun/java2d/marlin/ScaleTest.java b/test/jdk/sun/java2d/marlin/ScaleTest.java index bfd56422ba4..c9778a6477a 100644 --- a/test/jdk/sun/java2d/marlin/ScaleTest.java +++ b/test/jdk/sun/java2d/marlin/ScaleTest.java @@ -21,13 +21,17 @@ * questions. */ +/* @test + * @summary Circle is rendered in C shape + * @bug 6829659 8311666 + */ + import java.awt.*; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; import java.io.File; import javax.imageio.ImageIO; - public class ScaleTest { public static void main(String[] args) throws Exception { BufferedImage image = new BufferedImage(200, 200, BufferedImage.TYPE_INT_RGB); diff --git a/test/jdk/sun/java2d/marlin/StrokeShapeTest.java b/test/jdk/sun/java2d/marlin/StrokeShapeTest.java index 41413bff3e4..bc23f29e15d 100644 --- a/test/jdk/sun/java2d/marlin/StrokeShapeTest.java +++ b/test/jdk/sun/java2d/marlin/StrokeShapeTest.java @@ -20,6 +20,12 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +/* @test + * @summary StrokeShapeTest: createStrokedShape() behaves differently + * @bug 6829678 8311666 + */ + import java.awt.*; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; diff --git a/test/jdk/sun/java2d/marlin/ThinLineTest.java b/test/jdk/sun/java2d/marlin/ThinLineTest.java index a1a033c0bd4..7450f4e421d 100644 --- a/test/jdk/sun/java2d/marlin/ThinLineTest.java +++ b/test/jdk/sun/java2d/marlin/ThinLineTest.java @@ -20,6 +20,12 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + +/* @test + * @summary ThinLineTest: A line < 1 pixel disappears. + * @bug 6829673 8311666 + */ + import java.awt.*; import java.awt.geom.Ellipse2D; import java.awt.image.BufferedImage; diff --git a/test/jdk/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java b/test/jdk/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java index 114ddaa3022..568e28bdb18 100644 --- a/test/jdk/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java +++ b/test/jdk/sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2024, 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 @@ -323,10 +323,9 @@ public void terminate() { private void executeJava() throws Throwable { String className = JavaProcess.class.getName(); - String classPath = System.getProperty("test.classes"); - ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + ProcessBuilder pb = ProcessTools.createTestJvm( "-Dtest.timeout.factor=" + System.getProperty("test.timeout.factor", "1.0"), - "-cp", classPath, className, mainArgsIdentifier); + className, mainArgsIdentifier); OutputAnalyzer ob = ProcessTools.executeProcess(pb); System.out.println("Java Process " + getMainArgsIdentifier() + " stderr:" + ob.getStderr()); diff --git a/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java b/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java index 2756d008e77..93b9181a918 100644 --- a/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java +++ b/test/jdk/sun/management/jmxremote/bootstrap/RmiRegistrySslTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2024, 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 @@ -195,7 +195,7 @@ private int doTest(String... args) throws Exception { System.out.println("test output:"); System.out.println(output.getOutput()); - if (!output.getOutput().contains("Exception thrown by the agent : " + + if (!output.getOutput().contains("Exception thrown by the agent: " + "java.rmi.server.ExportException: Port already in use")) { return output.getExitValue(); } diff --git a/test/jdk/sun/misc/URLClassPath/LargeClasspathWithPkgPrefix.java b/test/jdk/sun/misc/URLClassPath/LargeClasspathWithPkgPrefix.java new file mode 100644 index 00000000000..1937f0b1f5d --- /dev/null +++ b/test/jdk/sun/misc/URLClassPath/LargeClasspathWithPkgPrefix.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2023, 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.nio.file.Files; +import java.nio.file.Path; + +import jdk.test.lib.JDKToolFinder; +import jdk.test.lib.compiler.CompilerUtils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +/* + * @test + * @bug 8308184 + * @summary Verify that an application can be launched when the classpath contains large number of + * jars and the java.protocol.handler.pkgs system property is set + * @library /lib/testlibrary/java/util/jar /test/lib/ + * @build JarBuilder jdk.test.lib.compiler.CompilerUtils + * jdk.test.lib.process.ProcessTools + * @run driver LargeClasspathWithPkgPrefix + */ +public class LargeClasspathWithPkgPrefix { + + private static final Path CWD = Path.of("."); + + private static final String JAVA_MAIN_CONTENT = + "public class Foo {\n" + + " public static void main(String[] args) throws Exception {\n" + + " if (args.length != 0) {\n" + + " System.out.println(\"unexpected args: \" + java.util.Arrays.toString(args));\n" + + " System.exit(1);\n" + + " }\n" + + " System.out.println(\"Running application on Java version: \"\n" + + " + System.getProperty(\"java.version\"));\n" + + " System.out.println(\"Application launched with java.protocol.handler.pkgs=\"\n" + + " + System.getProperty(\"java.protocol.handler.pkgs\"));\n" + + " System.out.println(\"Application launched with classpath: \"\n" + + " + System.getProperty(\"java.class.path\"));\n" + + " System.out.println(\"Hello World\");\n" + + " }\n" + + "}\n"; + + public static void main(final String[] args) throws Exception { + // dir to which the application main's .class file will be compiled to + Path classesDir = Files.createTempDirectory(CWD, "8308184-classes").toAbsolutePath(); + // dir contains many jars + Path libDir = Files.createTempDirectory(CWD, "8308184-libs").toAbsolutePath(); + Files.createDirectories(libDir); + + // trivial jar file + Path jarPath = Path.of(libDir.toString(), "8308184-dummy.jar"); + createJar(jarPath); + + // create multiple such jar files in the lib dir + int numCopies = 750; + long start = System.currentTimeMillis(); + for (int i = 1; i <= numCopies; i++) { + Path dest = Path.of(libDir.toString(), "8308184-dummy-" + i + ".jar"); + Files.copy(jarPath, dest); + } + long end = System.currentTimeMillis(); + System.out.println("Created " + numCopies + " jars under " + libDir + + ", took " + (end - start) + " milli seconds"); + + // create the application's main java file + Path fooJavaSrcFile = Path.of(classesDir.toString(), "Foo.java"); + Files.writeString(fooJavaSrcFile, JAVA_MAIN_CONTENT); + + // compile this java file + compile(fooJavaSrcFile, classesDir); + + // Create the classpath string. It is important that the classes directory which contains + // application's main class, is at the end of the classpath (or too far into the classpath). + // The initial entries in the classpath should be jar files. + // constructed classpath is of the form -cp lib/*:classes/ + // (the * in lib/* is parsed/interpreted by the java launcher and includes all jars in that + // directory) + String classpath = File.pathSeparator + libDir.toString() + "/*" + + File.pathSeparator + classesDir.toString(); + // launch the application + launchApplication(classpath); + // test passed successfully, we don't need the lib directory which has too many jars, + // anymore. we let the dir stay only if the test fails, for debug purpose + libDir.toFile().deleteOnExit(); + } + + // creates a trivial jar file + private static void createJar(Path p) throws Exception { + JarBuilder jb = new JarBuilder(p.toString()); + jb.addEntry("foobar.txt", "foobar".getBytes()); + jb.build(); + System.out.println("Created jar at " + p); + } + + // compile to + private static void compile(Path javaFile, Path destDir) throws Exception { + boolean compiled = CompilerUtils.compile(javaFile, destDir); + if (!compiled) { + // compilation failure log/reason would already be available on System.out/err + throw new AssertionError("Compilation failed for " + javaFile); + } + } + + // java -Djava.protocol.handler.pkgs=foo.bar.some.nonexistent.pkg -cp Foo + private static void launchApplication(String classPath) throws Exception { + String java = JDKToolFinder.getJDKTool("java"); + ProcessBuilder pb = new ProcessBuilder(java, + "-Djava.protocol.handler.pkgs=foo.bar.some.nonexistent.pkg", + "-cp", classPath, + "Foo"); + pb.directory(CWD.toFile()); + System.out.println("Launching java application: " + pb.command()); + OutputAnalyzer analyzer = ProcessTools.executeProcess(pb); + analyzer.shouldHaveExitValue(0); + analyzer.shouldContain("Hello World"); + } +} diff --git a/test/jdk/sun/net/www/http/HttpClient/KeepAliveTest.java b/test/jdk/sun/net/www/http/HttpClient/KeepAliveTest.java index 15983f3196a..0fdfb591a8c 100644 --- a/test/jdk/sun/net/www/http/HttpClient/KeepAliveTest.java +++ b/test/jdk/sun/net/www/http/HttpClient/KeepAliveTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,177 +24,29 @@ /* * @test * @library /test/lib - * @bug 8291226 8291638 - * @modules java.base/sun.net:+open - * java.base/sun.net.www.http:+open - * java.base/sun.net.www:+open + * @bug 8291226 8291638 8330523 + * @modules java.base/sun.net.www.http:+open * java.base/sun.net.www.protocol.http:+open - * @run main/othervm KeepAliveTest 0 - * @run main/othervm KeepAliveTest 1 - * @run main/othervm KeepAliveTest 2 - * @run main/othervm KeepAliveTest 3 - * @run main/othervm KeepAliveTest 4 - * @run main/othervm KeepAliveTest 5 - * @run main/othervm KeepAliveTest 6 - * @run main/othervm KeepAliveTest 7 - * @run main/othervm KeepAliveTest 8 - * @run main/othervm KeepAliveTest 9 - * @run main/othervm KeepAliveTest 10 - * @run main/othervm KeepAliveTest 11 - * @run main/othervm KeepAliveTest 12 - * @run main/othervm KeepAliveTest 13 - * @run main/othervm KeepAliveTest 14 - * @run main/othervm KeepAliveTest 15 - * @run main/othervm KeepAliveTest 16 - * @run main/othervm KeepAliveTest 17 - * @run main/othervm KeepAliveTest 18 - * @run main/othervm KeepAliveTest 19 - * @run main/othervm KeepAliveTest 20 - * @run main/othervm KeepAliveTest 21 - * @run main/othervm KeepAliveTest 22 - * @run main/othervm KeepAliveTest 23 - * @run main/othervm KeepAliveTest 24 - * @run main/othervm KeepAliveTest 25 - * @run main/othervm KeepAliveTest 26 - * @run main/othervm KeepAliveTest 27 - * @run main/othervm KeepAliveTest 28 - * @run main/othervm KeepAliveTest 29 - * @run main/othervm KeepAliveTest 30 - * @run main/othervm KeepAliveTest 31 - * @run main/othervm KeepAliveTest 32 - * @run main/othervm KeepAliveTest 33 - * @run main/othervm KeepAliveTest 34 - * @run main/othervm KeepAliveTest 35 - * @run main/othervm KeepAliveTest 36 - * @run main/othervm KeepAliveTest 37 - * @run main/othervm KeepAliveTest 38 - * @run main/othervm KeepAliveTest 39 - * @run main/othervm KeepAliveTest 40 - * @run main/othervm KeepAliveTest 41 - * @run main/othervm KeepAliveTest 42 - * @run main/othervm KeepAliveTest 43 - * @run main/othervm KeepAliveTest 44 - * @run main/othervm KeepAliveTest 45 - * @run main/othervm KeepAliveTest 46 - * @run main/othervm KeepAliveTest 47 - * @run main/othervm KeepAliveTest 48 - * @run main/othervm KeepAliveTest 49 - * @run main/othervm KeepAliveTest 50 - * @run main/othervm KeepAliveTest 51 - * @run main/othervm KeepAliveTest 52 - * @run main/othervm KeepAliveTest 53 - * @run main/othervm KeepAliveTest 54 - * @run main/othervm KeepAliveTest 55 - * @run main/othervm KeepAliveTest 56 - * @run main/othervm KeepAliveTest 57 - * @run main/othervm KeepAliveTest 58 - * @run main/othervm KeepAliveTest 59 - * @run main/othervm KeepAliveTest 60 - * @run main/othervm KeepAliveTest 61 - * @run main/othervm KeepAliveTest 62 - * @run main/othervm KeepAliveTest 63 - * @run main/othervm KeepAliveTest 64 - * @run main/othervm KeepAliveTest 65 - * @run main/othervm KeepAliveTest 66 - * @run main/othervm KeepAliveTest 67 - * @run main/othervm KeepAliveTest 68 - * @run main/othervm KeepAliveTest 69 - * @run main/othervm KeepAliveTest 70 - * @run main/othervm KeepAliveTest 71 - * @run main/othervm KeepAliveTest 72 - * @run main/othervm KeepAliveTest 73 - * @run main/othervm KeepAliveTest 74 - * @run main/othervm KeepAliveTest 75 - * @run main/othervm KeepAliveTest 76 - * @run main/othervm KeepAliveTest 77 - * @run main/othervm KeepAliveTest 78 - * @run main/othervm KeepAliveTest 79 - * @run main/othervm KeepAliveTest 80 - * @run main/othervm KeepAliveTest 81 - * @run main/othervm KeepAliveTest 82 - * @run main/othervm KeepAliveTest 83 - * @run main/othervm KeepAliveTest 84 - * @run main/othervm KeepAliveTest 85 - * @run main/othervm KeepAliveTest 86 - * @run main/othervm KeepAliveTest 87 - * @run main/othervm KeepAliveTest 88 - * @run main/othervm KeepAliveTest 89 - * @run main/othervm KeepAliveTest 90 - * @run main/othervm KeepAliveTest 91 - * @run main/othervm KeepAliveTest 92 - * @run main/othervm KeepAliveTest 93 - * @run main/othervm KeepAliveTest 94 - * @run main/othervm KeepAliveTest 95 - * @run main/othervm KeepAliveTest 96 - * @run main/othervm KeepAliveTest 97 - * @run main/othervm KeepAliveTest 98 - * @run main/othervm KeepAliveTest 99 - * @run main/othervm KeepAliveTest 100 - * @run main/othervm KeepAliveTest 101 - * @run main/othervm KeepAliveTest 102 - * @run main/othervm KeepAliveTest 103 - * @run main/othervm KeepAliveTest 104 - * @run main/othervm KeepAliveTest 105 - * @run main/othervm KeepAliveTest 106 - * @run main/othervm KeepAliveTest 107 - * @run main/othervm KeepAliveTest 108 - * @run main/othervm KeepAliveTest 109 - * @run main/othervm KeepAliveTest 110 - * @run main/othervm KeepAliveTest 111 - * @run main/othervm KeepAliveTest 112 - * @run main/othervm KeepAliveTest 113 - * @run main/othervm KeepAliveTest 114 - * @run main/othervm KeepAliveTest 115 - * @run main/othervm KeepAliveTest 116 - * @run main/othervm KeepAliveTest 117 - * @run main/othervm KeepAliveTest 118 - * @run main/othervm KeepAliveTest 119 - * @run main/othervm KeepAliveTest 120 - * @run main/othervm KeepAliveTest 121 - * @run main/othervm KeepAliveTest 122 - * @run main/othervm KeepAliveTest 123 - * @run main/othervm KeepAliveTest 124 - * @run main/othervm KeepAliveTest 125 - * @run main/othervm KeepAliveTest 126 - * @run main/othervm KeepAliveTest 127 - * @run main/othervm KeepAliveTest 128 - * @run main/othervm KeepAliveTest 129 - * @run main/othervm KeepAliveTest 130 - * @run main/othervm KeepAliveTest 131 - * @run main/othervm KeepAliveTest 132 - * @run main/othervm KeepAliveTest 133 - * @run main/othervm KeepAliveTest 134 - * @run main/othervm KeepAliveTest 135 - * @run main/othervm KeepAliveTest 136 - * @run main/othervm KeepAliveTest 137 - * @run main/othervm KeepAliveTest 138 - * @run main/othervm KeepAliveTest 139 - * @run main/othervm KeepAliveTest 140 - * @run main/othervm KeepAliveTest 141 - * @run main/othervm KeepAliveTest 142 - * @run main/othervm KeepAliveTest 143 - * @run main/othervm KeepAliveTest 144 - * @run main/othervm KeepAliveTest 145 - * @run main/othervm KeepAliveTest 146 - * @run main/othervm KeepAliveTest 147 - * @run main/othervm KeepAliveTest 148 - * @run main/othervm KeepAliveTest 149 - * @run main/othervm KeepAliveTest 150 - * @run main/othervm KeepAliveTest 151 - * @run main/othervm KeepAliveTest 152 - * @run main/othervm KeepAliveTest 153 - * @run main/othervm KeepAliveTest 154 - * @run main/othervm KeepAliveTest 155 - * @run main/othervm KeepAliveTest 156 - * @run main/othervm KeepAliveTest 157 - * @run main/othervm KeepAliveTest 158 - * @run main/othervm KeepAliveTest 159 + * @run main/othervm KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=100 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.proxy=200 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=100 -Dhttp.keepAlive.time.proxy=200 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=-100 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.proxy=-200 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=-100 -Dhttp.keepAlive.time.proxy=-200 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=0 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.proxy=0 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=0 -Dhttp.keepAlive.time.proxy=0 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=0 -Dhttp.keepAlive.time.proxy=-200 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=-100 -Dhttp.keepAlive.time.proxy=0 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=100 -Dhttp.keepAlive.time.proxy=0 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=0 -Dhttp.keepAlive.time.proxy=200 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=100 -Dhttp.keepAlive.time.proxy=-200 KeepAliveTest + * @run main/othervm -Dhttp.keepAlive.time.server=-100 -Dhttp.keepAlive.time.proxy=200 KeepAliveTest */ - -import java.nio.charset.StandardCharsets; -import java.io.InputStream; import java.io.BufferedReader; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.lang.reflect.Constructor; @@ -206,841 +58,59 @@ import java.net.ServerSocket; import java.net.Socket; import java.net.URL; +import java.nio.charset.StandardCharsets; import java.util.List; import java.util.Map.Entry; -import java.util.concurrent.CountDownLatch; +import java.util.concurrent.Phaser; import java.util.logging.ConsoleHandler; import java.util.logging.Level; import java.util.logging.Logger; + +import jdk.test.lib.net.URIBuilder; + import sun.net.www.http.HttpClient; import sun.net.www.http.KeepAliveCache; import sun.net.www.protocol.http.HttpURLConnection; -import jdk.test.lib.net.URIBuilder; public class KeepAliveTest { - private static final Logger logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection"); - private static final String NOT_CACHED = "NotCached"; - private static final String CLIENT_SEPARATOR = ";"; - private static final String NEW_LINE = "\r\n"; - private volatile int SERVER_PORT = 0; + /* - * isProxySet is shared variable between server thread and client thread(main) and it should be set and reset to false for each and - * every scenario. - * isProxySet variable should be set by server thread before proceeding to client thread(main). + * This test covers a matrix of 10 server scenarios and 16 client scenarios. */ - private volatile boolean isProxySet = false; + private static final Logger logger = Logger.getLogger("sun.net.www.protocol.http.HttpURLConnection"); + + private static final String NEW_LINE = "\r\n"; + private static final String CONNECTION_KEEP_ALIVE_ONLY = "Connection: keep-alive"; private static final String PROXY_CONNECTION_KEEP_ALIVE_ONLY = "Proxy-Connection: keep-alive"; private static final String KEEP_ALIVE_TIMEOUT_NEG = "Keep-alive: timeout=-20"; private static final String KEEP_ALIVE_TIMEOUT_ZERO = "Keep-alive: timeout=0"; private static final String KEEP_ALIVE_TIMEOUT = "Keep-alive: timeout=20"; private static final String KEEP_ALIVE_PROXY_TIMEOUT = "Keep-alive: timeout=120"; - private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_NEGATIVE = "http.keepAlive.time.server=-100"; - private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_NEGATIVE = "http.keepAlive.time.proxy=-200"; - private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_ZERO = "http.keepAlive.time.server=0"; - private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_ZERO = "http.keepAlive.time.proxy=0"; - private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_POSITIVE = "http.keepAlive.time.server=100"; - private static final String CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_POSITIVE = "http.keepAlive.time.proxy=200"; - private static final String CONNECTION_KEEP_ALIVE_WITH_TIMEOUT = CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE - + KEEP_ALIVE_TIMEOUT; - /* - * Following Constants represents Client Side Properties and is used as reference in below table as - * CLIENT_INPUT_CONSTANT_NAMES - */ - private static final String SERVER_100_NEGATIVE = CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_NEGATIVE; - private static final String PROXY_200_NEGATIVE = CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_NEGATIVE; - private static final String SERVER_ZERO = CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_ZERO; - private static final String PROXY_ZERO = CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_ZERO; - private static final String SERVER_100 = CLIENT_HTTP_KEEP_ALIVE_TIME_SERVER_POSITIVE; - private static final String PROXY_200 = CLIENT_HTTP_KEEP_ALIVE_TIME_PROXY_POSITIVE; - - /* - * CONSTANTS A,B,C,D,E,NI,F,G,H,I represents ServerScenarios and is used as reference in below table - * as SERVER_RESPONSE_CONSTANT_NAME - */ - private static final String A = CONNECTION_KEEP_ALIVE_ONLY; - private static final String B = CONNECTION_KEEP_ALIVE_WITH_TIMEOUT; - private static final String C = PROXY_CONNECTION_KEEP_ALIVE_ONLY; - private static final String D = PROXY_CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE + CONNECTION_KEEP_ALIVE_ONLY; - private static final String E = C + NEW_LINE + KEEP_ALIVE_PROXY_TIMEOUT; - private static final String NI = "NO_INPUT"; - private static final String F = A + NEW_LINE + KEEP_ALIVE_TIMEOUT_NEG; - private static final String G = A + NEW_LINE + KEEP_ALIVE_TIMEOUT_ZERO; - private static final String H = C + NEW_LINE + KEEP_ALIVE_TIMEOUT_NEG; - private static final String I = C + NEW_LINE + KEEP_ALIVE_TIMEOUT_ZERO; - - /* - * There are 160 scenarios run by this program. - * For every scenario there is mapping between serverScenarios[int],clientScenarios[int] and expectedOutput[int] - * - * serverScenarios[0] clientScenarios[0] expectedOutput[0] - * serverScenarios[1] clientScenarios[1] expectedOutput[1] - * serverScenarios[2] clientScenarios[2] expectedOutput[2] - * - * ... - * - * serverScenarios[159] cientScenarios[159] expectedOutput[159] - * - * whereas serverScenarios[int] is retrieved using getServerScenario(int) - * whereas clientScenarios[int] is retrieved using clientScenario[getClientScenarioNumber[int]] - * and - * expectedOutput[int] is retrieved using expectedOuput[int] directly. - * - */ - - /* Here is the complete table of server_response, client system properties input and expected cached timeout at client side */ - /* ScNo | SERVER RESPONSE (SERVER_RESPONSE_CONSTANT_NAME)| CLIENT SYSTEM PROPERTIES INPUT (CLIENT_INPUT_CONSTANT_NAMES) | EXPECTED CACHED TIMEOUT AT CLIENT SIDE - ***************************************************************************************************************************************** - * 0 | Connection: keep-alive (A) | No Input Provided (NI) | Default Timeout set to 5 - *--------------------------------------------------------------------------------------------------------------------------- - * 1 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=100 (SERVER_100)| Client Timeout set to 100 - *-------------------------------------------------------------------------------------------------------------------------- - * 2 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.proxy=200 (PROXY_200) | Default Timeout set to 5 - *--------------------------------------------------------------------------------------------------------------------------- - * 3 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 100 - * | | (SERVER_100 && PROXY_200) | - *--------------------------------------------------------------------------------------------------------------------------- - * 4 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=-100 | Default Timeout set to 5 - * | | (SERVER_100_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 5 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.proxy=-200 | Default Timeout set to 5 - * | | (PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 6 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=-100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Default Timeout set to 5 - * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 7 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=0 | Connection Closed Immediately - * | | (SERVER_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 8 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.proxy=0 | Default Timeout set to 5 - * | | (PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 9 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=0 | Connection Closed Immediately - * | | (SERVER_ZERO && PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 10 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Connection Closed Immediately - * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 11 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=-100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | Default Timeout set to 5 - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 12 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 100 - * | | (SERVER_100 && PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 13 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Connection Closed Immediately - * | | (SERVER_ZERO && PROXY_200) | - *--------------------------------------------------------------------------------------------------------------------------- - * 14 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 100 - * | | (SERVER_100 && PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 15 | Connection: keep-alive (A) | -Dhttp.keepAlive.time.server=-100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Default Timeout set to 5 - * | | (SERVER_100_NEGATIVE && PROXY_200) | - *--------------------------------------------------------------------------------------------------------------------------- - * 16 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | No Input Provided (NI) | Timeout set to 20 - *------------------------------------------------------------------------------------------------------------------------ - * 17 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=100 | Timeout set to 20 - * | | (SERVER_100) | - *--------------------------------------------------------------------------------------------------------------------------- - * 18 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 20 - * | | (PROXY_200) | - *--------------------------------------------------------------------------------------------------------------------------- - * 19 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 20 - * | | (SERVER_100 && PROXY_200) | - *--------------------------------------------------------------------------------------------------------------------------- - * 20 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=-100 | Timeout set to 20 - * | | (SERVER_100_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 21 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 20 - * | | (PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 22 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=-100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 20 - * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| - *--------------------------------------------------------------------------------------------------------------------------- - * 23 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=0 | Timeout set to 20 - * | | (SERVER_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 24 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 20 - * | | (PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 25 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 20 - * | | (SERVER_ZERO && PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 26 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 20 - * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 27 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=-100 &&| - * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 20 - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 28 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 20 - * | | (SERVER_100 && PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 29 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 20 - * | | (SERVER_ZERO && PROXY_200) | - *--------------------------------------------------------------------------------------------------------------------------- - * 30 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 20 - * | | (SERVER_100 && PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 31 |Connection: keep-alive\r\nKeep-alive: timeout=20 (B) |-Dhttp.keepAlive.time.server=-100 && | - * | |-Dhttp.keepAlive.time.proxy=200 | Timeout set to 20 - * | | (SERVER_100_NEGATIVE && PROXY_200) | - *--------------------------------------------------------------------------------------------------------------------------- - * 32 |Proxy-Connection: keep-alive (C) | No Input Provided (NI) | Default timeout set to 60 - *--------------------------------------------------------------------------------------------------------------------------- - * 33 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=100 | Default timeout set to 60 - * | | (SERVER_100) | - *--------------------------------------------------------------------------------------------------------------------------- - * 34 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------- - * 35 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (SERVER_100 && PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------- - * 36 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=-100 | Default timeout set to 60 - * | | (SERVER_100_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 37 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 - * | | (PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 38 |Proxy-Connection: keep-alive (C) |-Dhttp.keepAlive.time.server=-100 && | - * | |-Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 - * | |(SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| - *--------------------------------------------------------------------------------------------------------------------------- - * 39 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=0 | Default timeout set to 60 - * | | (SERVER_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 40 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 41 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_ZERO && PROXY_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 42 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 - * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------------- - * 43 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=-100 &&| - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------------- - * 44 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_100 && PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 45 |Proxy-Connection: keep-alive (C) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (SERVER_ZERO && PROXY_200) | - *--------------------------------------------------------------------------------------------------------------------------- - * 46 |Proxy-Connection: keep-alive (C) |-Dhttp.keepAlive.time.server=100 && | - * | |-Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 - * | | (SERVER_100 && PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------- - * 47 |Proxy-Connection: keep-alive (C) |-Dhttp.keepAlive.time.server=-100 && | - * | |-Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------- - * 48 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | No Input Provided (NI) | Default timeout set to 60 - *----------------------------------------------------------------------------------------------------------------------------- - * 49 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=100 | Default timeout set to 60 - * | | (SERVER_100) | - *--------------------------------------------------------------------------------------------------------------------------- - * 50 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------ - * 51 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (SERVER_100 && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------ - * 52 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=-100 | Default timeout set to 60 - * | | (SERVER_100_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------ - * 53 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 - * | | (PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------ - * 54 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=-100&& | - * | | -Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 - * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE | - *------------------------------------------------------------------------------------------------------------------------------- - * 55 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=0 | Default timeout set to 60 - * | | (SERVER_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 56 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (PROXY_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 57 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_ZERO && PROXY_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 58 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Default timeout set to 60 - * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 59 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=-100 &&| - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 60 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_100 && PROXY_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 61 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (SERVER_ZERO && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------ - * 62 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | default timeout set to 60 - * | | (SERVER_100 && PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------ - * 63 |Connection:keep-alive\r\nProxy-connection:keep-alive (D) | -Dhttp.keepAlive.time.server=-100 &&| - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (SERVER_100_NEGATIVE && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------- - * 64 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| No Input Provided (NI) | Timeout set to 120 - *------------------------------------------------------------------------------------------------------------------------------- - * 65 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=100 | Timeout set to 120 - * | | (SERVER_100) | - *------------------------------------------------------------------------------------------------------------------------------- - * 66 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.proxy=200 | Timeout set to 120 - * | | (PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------- - * 67 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 120 - * | | (SERVER_100 && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------- - * 68 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=-100 | Timeout set to 120 - * | | (SERVER_100_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------- - * 69 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 120 - * | | (PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------- - * 70 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=-100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 120 - * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| - *------------------------------------------------------------------------------------------------------------------------------- - * 71 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=0 | Timeout set to 120 - * | | (SERVER_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------- - * 72 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.proxy=0 | Timeout set to 120 - * | | (PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------- - * 73 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 120 - * | | (SERVER_ZERO && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------- - * 74 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 120 - * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------- - * 75 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=-100 &&| - * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 120 - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------- - * 76 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 120 - * | | (SERVER_100 && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------- - * 77 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 120 - * | | (SERVER_ZERO && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------- - * 78 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | Timeout set to 120 - * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------- - * 79 |Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 (E)| -Dhttp.keepAlive.time.server=-100 &&| - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 120 - * | | (SERVER_100_NEGATIVE && PROXY_200) | - *----------------------------------------------------------------------------------------------------------------------------- - * 80 |No Input (NI) | No Input Provided (NI) | default timeout set to 5 - *----------------------------------------------------------------------------------------------------------------------------- - * 81 |No Input (NI) | -Dhttp.keepAlive.time.server=100 | Timeout set to 100 - * | | (SERVER_100) | - *----------------------------------------------------------------------------------------------------------------------------- - * 82 |No Input (NI) | -Dhttp.keepAlive.time.proxy=200 | default timeout set to 5 - * | | (PROXY_200) | - *----------------------------------------------------------------------------------------------------------------------------- - * 83 |No Input (NI) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | client timeot set to 100 - * | | (SERVER_100 && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------ - * 84 |No Input (NI) | -Dhttp.keepAlive.time.server=-100 | default timeout set to 5 - * | | (SERVER_100_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------ - * 85 |No Input (NI) | -Dhttp.keepAlive.time.proxy=-200 | default timeout set to 5 - * | | (PROXY_200_NEGATIVE) | - *---------------------------------------------------------------------------------------------------------------------------- - * 86 |No Input (NI) | -Dhttp.keepAlive.time.server=-100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | default timeout set to 5 - * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| - *------------------------------------------------------------------------------------------------------------------------------ - * 87 |No Input (NI) | -Dhttp.keepAlive.time.server=0 | close connection immediately - * | | (SERVER_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------------- - * 88 |No Input (NI) | -Dhttp.keepAlive.time.proxy=0 | default timeout set to 5 - * | | (PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------------- - * 89 |No Input (NI) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_ZERO && PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------------- - * 90 |No Input (NI) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately - * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 91 |No Input (NI) | -Dhttp.keepAlive.time.server=-100 &&| - * | | -Dhttp.keepAlive.time.proxy=0 | default timeout set to 5 - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 92 |No Input (NI) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | Timeout set to 100 - * | | (SERVER_100 && PROXY_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 93 |No Input (NI) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately - * | | (SERVER_ZERO && PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 94 |No Input (NI) |-Dhttp.keepAlive.time.server=100 && | - * | |-Dhttp.keepAlive.time.proxy=-200 | Timeout set to 100 - * | | (SERVER_100 && PROXY_200_NEGATIVE) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 95 |No Input (NI) |-Dhttp.keepAlive.time.server=-100 && | - * | |-Dhttp.keepAlive.time.proxy=200 | default timeout set to 5 - * | | (SERVER_100_NEGATIVE && PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 96 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) | No Input Provided (NI) | default timeout set to 5 - *-------------------------------------------------------------------------------------------------------------------------------- - * 97 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=100 | Timeout set to 100 - * | | (SERVER_100) | - *-------------------------------------------------------------------------------------------------------------------------------- - * 98 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.proxy=200 | default timeout set to 5 - * | | (PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 99 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=100 && | - * | |-Dhttp.keepAlive.time.proxy=200 | Timeout set to 100 - * | |(SERVER_100 && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 100 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=-100 | default timeout set to 5 - * | |(SERVER_100_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 101 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.proxy=-200 | default timeout set to 5 - * | |(PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 102 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=-100 && | - * | |-Dhttp.keepAlive.time.proxy=-200 | default timeout set to 5 - * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| - *------------------------------------------------------------------------------------------------------------------------------------- - * 103 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=0 | close connection immediately - * | | (SERVER_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 104 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.proxy=0 | default timeout set to 5 - * | | (PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 105 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_ZERO && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 106 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=0 && | - * | |-Dhttp.keepAlive.time.proxy=-200 | close connection immediately - * | | (SERVER_ZERO && PROXY_ZERO_NEGATIVE)| - *------------------------------------------------------------------------------------------------------------------------------------- - * 107 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=-100 && | - * | |-Dhttp.keepAlive.time.proxy=0 | default timeout set to 5 - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 108 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=100 && | - * | |-Dhttp.keepAlive.time.proxy=0 | Timeout set to 100 - * | | (SERVER_100 && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 109 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=0 && | - * | |-Dhttp.keepAlive.time.proxy=200 | close connection immediately - * | | (SERVER_ZERO && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 110 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=100 && | - * | |-Dhttp.keepAlive.time.proxy=-200 | Timeout set to 100 - * | |(SERVER_100 && PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 111 |Connection: keep-alive\r\nKeep-alive: timeout=-20 (F) |-Dhttp.keepAlive.time.server=-100 && | - * | |-Dhttp.keepAlive.time.proxy=200 | default timeout set to 5 - * | | (SERVER_100_NEGATIVE && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 112 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | No Input Provided (NI) | close connection immediately - *------------------------------------------------------------------------------------------------------------------------------------- - * 113 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=100 | close connection immediately - * | | (SERVER_100) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 114 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.proxy=200 | close connection immediately - * | | (PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 115 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately - * | | (SERVER_100 && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 116 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=-100 | close connection immediately - * | | (SERVER_100_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------ - * 117 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately - * | | (PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 118 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) |-Dhttp.keepAlive.time.server=-100 && | - * | |-Dhttp.keepAlive.time.proxy=-200 | close connection immediately - * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 119 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=0 | close connection immediately - * | | (SERVER_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 120 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------ - * 121 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_ZERO && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 122 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately - * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 123 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=-100 &&| - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 124 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_100 && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 125 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately - * | | (SERVER_ZERO && PROXY_200) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 126 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately - * | | (SERVER_100 && PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 127 |Connection: keep-alive\r\nKeep-alive: timeout=0 (G) | -Dhttp.keepAlive.time.server=-100 &&| - * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately - * | | (SERVER_100_NEGATIVE && PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 128 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| No Input Provided (NI) | default timeout set to 60 - --------------------------------------------------------------------------------------------------------------------------------------- - * 129 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=100 | default timeout set to 60 - * | | (SERVER_100) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 130 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 131 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (SERVER_100 && PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 132 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=-100 | default timeout set to 60 - * | | (SERVER_100_NEGATIVE) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 133 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.proxy=-200 | default timeout set to 60 - * | | (PROXY_200_NEGATIVE) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 134 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)|-Dhttp.keepAlive.time.server=-100 && | - * | |-Dhttp.keepAlive.time.proxy=-200 | default timeout set to 60 - * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE)| - *--------------------------------------------------------------------------------------------------------------------------------- - * 135 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=0 | default timeout set to 60 - * | | (SERVER_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 136 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (PROXY_ZERO) | - *---------------------------------------------------------------------------------------------------------------------------------- - * 137 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_ZERO && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 138 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | default timeout set to 60 - * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | - *--------------------------------------------------------------------------------------------------------------------------------------- - * 139 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=-100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 140 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_100 && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 141 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)| -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=200 | Timeout set to 20 - * | | (SERVER_ZERO && PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 142 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)|-Dhttp.keepAlive.time.server=100 && | - * | |-Dhttp.keepAlive.time.proxy=-200 | default timeout set to 60 - * | | (SERVER_100 && PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 143 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=-20 (H)|-Dhttp.keepAlive.time.server=-100 && | - * | |-Dhttp.keepAlive.time.proxy=200 | Timeout set to 200 - * | | (SERVER_100_NEGATIVE && PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 144 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | No Input Provided (NI) | close connection immediately - *-------------------------------------------------------------------------------------------------------------------------------------- - * 145 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=100 | close connection immediately - * | | (SERVER_100) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 146 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.proxy=200 | close connection immediately - * | | (PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 147 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately - * | | (SERVER_100 && PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 148 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=-100 | close connection immediately - * | | (SERVER_100_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 149 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately - * | | (PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 150 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=-100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately - * | | (SERVER_100_NEGATIVE && PROXY_200_NEGATIVE) | - *------------------------------------------------------------------------------------------------------------------------------------ - * 151 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=0 | close connection immediately - * | | (SERVER_ZERO) | - *----------------------------------------------------------------------------------------------------------------------------------- - * 152 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (PROXY_ZERO) | - *--------------------------------------------------------------------------------------------------------------------------------- - * 153 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_ZERO && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------ - * 154 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately - * | | (SERVER_ZERO && PROXY_200_NEGATIVE) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 155 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=-100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_100_NEGATIVE && PROXY_ZERO) | - *------------------------------------------------------------------------------------------------------------------------------------- - * 156 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=0 | close connection immediately - * | | (SERVER_100 && PROXY_ZERO) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 157 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=0 && | - * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately - * | | (SERVER_ZERO && PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 158 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=100 && | - * | | -Dhttp.keepAlive.time.proxy=-200 | close connection immediately - * | | (SERVER_100 && PROXY_200_NEGATIVE) | - *-------------------------------------------------------------------------------------------------------------------------------------- - * 159 |Proxy-Connection:keep-alive\r\nKeep-alive:timeout=0 (I) | -Dhttp.keepAlive.time.server=-100 && | - * | | -Dhttp.keepAlive.time.proxy=200 | close connection immediately - * | | (SERVER_100_NEGATIVE && PROXY_200) | - *-------------------------------------------------------------------------------------------------------------------------------------- - */ - - /* private static final String[] serverScenarios = { - A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, - B, B, B, B, B, B, B, B, B, B,B, B, B, B, B, B, - C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, C, - D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, D, - E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, E, - NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, NI, - F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, F, - G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, G, - H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, H, - I, I, I, I, I, I, I, I, I, I, I, I, I, I, I, I - }; */ - /* - * following are client scenarios which are repeated. - */ - private static final String[] a = { - NI, SERVER_100, PROXY_200, SERVER_100 + CLIENT_SEPARATOR + PROXY_200, SERVER_100_NEGATIVE, - PROXY_200_NEGATIVE, SERVER_100_NEGATIVE + CLIENT_SEPARATOR + PROXY_200_NEGATIVE, - SERVER_ZERO, PROXY_ZERO, SERVER_ZERO + CLIENT_SEPARATOR + PROXY_ZERO, - SERVER_ZERO + CLIENT_SEPARATOR + PROXY_200_NEGATIVE, SERVER_100_NEGATIVE + CLIENT_SEPARATOR + PROXY_ZERO, - SERVER_100 + CLIENT_SEPARATOR + PROXY_ZERO, SERVER_ZERO + CLIENT_SEPARATOR + PROXY_200, - SERVER_100 + CLIENT_SEPARATOR + PROXY_200_NEGATIVE, SERVER_100_NEGATIVE + CLIENT_SEPARATOR + PROXY_200 - }; - - /* private String[] clientScenarios = { - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15], - }; */ + private static final String CONNECTION_KEEP_ALIVE_WITH_TIMEOUT = CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE + KEEP_ALIVE_TIMEOUT; - private static final String[] clientScenarios = { - a[0] , a[1], a[2], a[3], a[4], a[5], a[6], a[7], a[8], a[9], a[10], a[11], a[12], a[13], a[14], a[15] + private static final String[] serverHeaders = { + null, + CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE, + CONNECTION_KEEP_ALIVE_WITH_TIMEOUT + NEW_LINE, + PROXY_CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE, + PROXY_CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE + CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE, + PROXY_CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE + KEEP_ALIVE_PROXY_TIMEOUT + NEW_LINE, + CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE + KEEP_ALIVE_TIMEOUT_NEG + NEW_LINE, + CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE + KEEP_ALIVE_TIMEOUT_ZERO + NEW_LINE, + PROXY_CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE + KEEP_ALIVE_TIMEOUT_NEG + NEW_LINE, + PROXY_CONNECTION_KEEP_ALIVE_ONLY + NEW_LINE + KEEP_ALIVE_TIMEOUT_ZERO + NEW_LINE }; - private static final int[] expectedValues = { - 5, 100, 5, 100, 5, 5, 5, 0, 5, 0, 0, 5, 100, 0, 100, 5, - 20, 20 , 20, 20, 20, 20, 20, 20, 20, 20 , 20, 20, 20, 20, 20, 20, - 60, 60, 200, 200, 60, 60, 60, 60, 0, 0, 60, 0, 0, 200, 60, 200, - 60, 60, 200, 200, 60, 60, 60, 60, 0, 0, 60, 0, 0, 200, 60, 200, - 120, 120, 120, 120,120,120,120,120,120, 120, 120, 120, 120, 120, 120, 120, - 5, 100, 5, 100, 5, 5, 5, 0, 5, 0, 0, 5, 100, 0, 100, 5, - 5, 100, 5, 100, 5, 5, 5, 0, 5, 0, 0, 5, 100, 0, 100, 5, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 60, 60, 200, 200, 60, 60, 60, 60, 0, 0, 60, 0, 0, 200, 60, 200, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - }; + private static KeepAliveCache keepAliveCache; - private final CountDownLatch countDownLatch = new CountDownLatch(1); + private static Constructor keepAliveKeyClassconstructor; - private final CountDownLatch serverCountDownLatch = new CountDownLatch(1); + // variables set by server thread + private volatile int serverPort; + private volatile boolean isProxySet; - /* - * setting of client properties -Dhttp.keepAlive.time.server and -Dhttp.keepAlive.time.proxy is handled through this method. - * There are 16 client scenarios in total starting with scenarioNumber 0(zero) and ending with 15. - * Server Scenarios are grouped into batch of 16 scenarios. - * There are 10 batches in total and each batch contains 16 scenarios so 10 * 16 = 160 scenarios in total. - * 16 Client Scenarios are used repeatedly for every server scenario batch. - * for serverscenario[0],serverscenario[16],serverscenario[32] ... serverscenario[144] is mapped to clientscenario[0] - * for serverscenario[1],serverscenario[17],serverscenario[33] ... serverscenario[145] is mapped to clientscenario[1] - * for serverscenario[2],serverscenario[18],serverscenario[34] ... serverscenario[146] is mapped to clientscenario[2] - * ... - * for serverscenario[15],serverscenario[31],serverscenario[47] ... serverscenario[159] is mapped to clientscenario[15] - */ - private int getClientScenarioNumber(int scenarioNumber) { - return scenarioNumber % 16 ; - } - - /* - * Returns SERVER_RESPONSE as String based on integer inputParameter scenarioNumber. - * Server Scenarios are grouped into batch of 16 scenarios starting with scenarioNumber 0 (zero) - * so there are 10 batches in total and each batch contains 16 scenarios so 10 * 16 = 160 scenarios in total. - * For each batch of 16 scenarios, there will be common SERVER_RESPONSE for all 16 scenarios in batch. - * for scenario numbers from 0 to 15 server response is: Connection:keep-alive - * for scenario numbers from 16 to 31 server response is: SERVER_RESPONSE=Connection: keep-alive\r\nKeep-alive: timeout=20 - * for scenario numbers from 32 to 47 server response is: SERVER_RESPONSE=Proxy-Connection: keep-alive - * for scenario numbers from 48 to 63 server response is: SERVER_RESPONSE=Connection:keep-alive\r\nProxy-connection:keep-alive - * for scenario numbers from 64 to 79 server response is: SERVER_RESPONSE=Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 - * for scenario numbers from 80 to 95 server response is: SERVER_RESPONSE=No Input - * for scenario numbers from 96 to 111 server response is: SERVER_RESPONSE=Connection: keep-alive\r\nKeep-alive: timeout=-20 - * for scenario numbers from 112 to 127 server resonse is: Connection: keep-alive\r\nKeep-alive: timeout=0 - * for scenario numbers from 128 to 143 server response is: Proxy-connection:keep-alive\r\nKeep-alive:timeout=-20 - * for scenario numbers from 144 to 159 server response is: Proxy-connection:keep-alive\r\nKeep-alive:timeout=0 - */ - private String getServerScenario(int scenarioNumber) { - /* - * ServerResponse for scenarios from 0 to 15 - * SERVER_RESPONSE:Connection:keep-alive - */ - if(scenarioNumber >= 0 && scenarioNumber <= 15) { - return A; - } - /* - * ServerResponse for scenarios from 16 to 31 - * SERVER_RESPONSE=Connection: keep-alive\r\nKeep-alive: timeout=20 - */ - else if (scenarioNumber >= 16 && scenarioNumber <= 31){ - return B; - } - /* - * ServerResponse for scenarios from 32 to 47 - * SERVER_RESPONSE=Proxy-Connection: keep-alive - */ - else if (scenarioNumber >= 32 && scenarioNumber <= 47){ - return C; - } - /* - * ServerResponse for scenarios from 48 to 63 - * SERVER_RESPONSE=Connection:keep-alive\r\nProxy-connection:keep-alive - */ - else if (scenarioNumber >= 48 && scenarioNumber <= 63){ - return D; - /* - * ServerResponse for scenarios from 64 to 79 - * SERVER_RESPONSE=Proxy-connection:keep-alive\r\nKeep-alive:timeout=120 - */ - } else if (scenarioNumber >= 64 && scenarioNumber <= 79){ - return E; - } - /* - * ServerResponse for scenarios from 80 to 95 - * SERVER_RESPONSE=No Input - */ - else if (scenarioNumber >= 80 && scenarioNumber <= 95){ - return NI; - } - /* - * ServerResponse for scenarios from 96 to 111 - * SERVER_RESPONSE=Connection: keep-alive\r\nKeep-alive: timeout=-20 - */ - else if (scenarioNumber >= 96 && scenarioNumber <= 111){ - return F; - } - /* - * ServerResponse for scenarios from 112 to 127 - * SERVER_RESPONSE=Connection: keep-alive\r\nKeep-alive: timeout=0 - */ - else if (scenarioNumber >= 112 && scenarioNumber <= 127){ - return G; - } - /* - * ServerResponse for scenarios from 128 to 143 - * SERVER_RESPONSE=Proxy-connection:keep-alive\r\nKeep-alive:timeout=-20 - */ - else if (scenarioNumber >= 128 && scenarioNumber <= 143){ - return H; - } - /* - * ServerResponse for scenarios from 144 to 159 - * SERVER_RESPONSE=Proxy-connection:keep-alive\r\nKeep-alive:timeout=0 - */ - else if (scenarioNumber >= 144 && scenarioNumber <= 159){ - return I; - } - /*Invalid Case*/ - return null; - } - - private void startScenario(int scenarioNumber) throws Exception { - System.out.println("serverScenarios[" + scenarioNumber + "]=" + getServerScenario(scenarioNumber)); - System.out.println("clientScenarios[" + scenarioNumber + "]=" + clientScenarios[getClientScenarioNumber(scenarioNumber)]); - if(expectedValues[scenarioNumber] == 0) { - System.out.println("ExpectedOutput=" + NOT_CACHED); - } else { - System.out.println("ExpectedOutput=" + expectedValues[scenarioNumber]); - } - System.out.println(); - startServer(scenarioNumber); - runClient(scenarioNumber); - } - - private void startServer(int scenarioNumber) { - Thread server = new Thread(new Runnable() { - @Override - public void run() { - try { - executeServer(scenarioNumber); - } catch (IOException e) { - e.printStackTrace(); - } - } - }, "SERVER"); - server.start(); - } + private static final Phaser serverGate = new Phaser(2); private void readAll(Socket s) throws IOException { byte[] buf = new byte[128]; @@ -1058,215 +128,209 @@ private void readAll(Socket s) throws IOException { } } - private void executeServer(int scenarioNumber) throws IOException { - String serverScenarioContent = null; - if (!getServerScenario(scenarioNumber).equalsIgnoreCase(NI)) { - serverScenarioContent = getServerScenario(scenarioNumber) + NEW_LINE; - /* - * isProxySet should be set before Server is moved to Listen State. - */ - if (serverScenarioContent.contains("Proxy")) { - isProxySet = true; - } else { - isProxySet = false; - } + private void executeServer(int scenarioNumber) { + String scenarioHeaders = serverHeaders[scenarioNumber]; + if (scenarioHeaders != null) { + // isProxySet should be set before Server is moved to Listen State. + isProxySet = scenarioHeaders.contains("Proxy"); } - ServerSocket serverSocket = null; - Socket socket = null; - OutputStreamWriter out = null; - InetAddress loopback = InetAddress.getLoopbackAddress(); - try { - serverSocket = new ServerSocket(); - serverSocket.bind(new InetSocketAddress(loopback, 0)); - SERVER_PORT = serverSocket.getLocalPort(); - //serverReady = true; - this.serverCountDownLatch.countDown(); - System.out - .println("SERVER_PORT= " + SERVER_PORT +" isProxySet=" + isProxySet); - /* - * Server will be waiting for clients to connect. - */ - socket = serverSocket.accept(); - readAll(socket); - out = new OutputStreamWriter(socket.getOutputStream()); - String BODY = "SERVER REPLY: Hello world"; - String CLEN = "Content-Length: " + BODY.length() + NEW_LINE; - /* send the header */ - out.write("HTTP/1.1 200 OK\r\n"); - out.write("Content-Type: text/plain; charset=iso-8859-1\r\n"); - /* - * append each scenario content from array. - */ - if(serverScenarioContent != null) { - out.write(serverScenarioContent); - } - out.write(CLEN); - out.write(NEW_LINE); - out.write(BODY); - out.flush(); - } catch (IOException e) { - e.printStackTrace(); - } finally { - if (out != null) { - out.flush(); - out.close(); - } - if (socket != null) { - socket.close(); - } - if (serverSocket != null) { - serverSocket.close(); + try (ServerSocket serverSocket = new ServerSocket()) { + serverSocket.bind(new InetSocketAddress(InetAddress.getLoopbackAddress(), 0)); + serverPort = serverSocket.getLocalPort(); + serverGate.arrive(); + + // Server will be waiting for clients to connect. + try (Socket socket = serverSocket.accept()) { + readAll(socket); + try (OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream())) { + String BODY = "SERVER REPLY: Hello world"; + String CLEN = "Content-Length: " + BODY.length() + NEW_LINE; + + // send common headers + out.write("HTTP/1.1 200 OK\r\n"); + out.write("Content-Type: text/plain; charset=iso-8859-1\r\n"); + + // set scenario headers + if (scenarioHeaders != null) { + out.write(scenarioHeaders); + } + + // send content + out.write(CLEN); + out.write(NEW_LINE); + out.write(BODY); + } } + } catch (IOException ioe) { + throw new RuntimeException("IOException in server thread", ioe); } } - private void runClient(int scenarioNumber) throws Exception { - try { - connectToServerURL(scenarioNumber); - } finally { - System.out.println("client count down latch:" + scenarioNumber); - this.countDownLatch.countDown(); - System.out.println(); - System.out.println(); - } - } + private void fetchInfo(int expectedValue, HttpURLConnection httpUrlConnection) throws Exception { + Object expectedKeepAliveKey = keepAliveKeyClassconstructor.newInstance(httpUrlConnection.getURL(), null); + Object clientVectorObjectInMap = keepAliveCache.get(expectedKeepAliveKey); + System.out.println("ClientVector for KeepAliveKey:" + clientVectorObjectInMap); + HttpClient httpClientCached = keepAliveCache.get(httpUrlConnection.getURL(), null); + System.out.println("HttpClient in Cache:" + httpClientCached); - private void connectToServerURL(int scenarioNumber) throws Exception { - // System.setProperty("java.net.useSystemProxies", "false"); - // System.setProperty("http.nonProxyHosts", ""); - // System.setProperty("http.proxyHost", "localhost"); - // System.setProperty("http.proxyPort", String.valueOf(SERVER_PORT)); - System.out.println("Following are Existing System Properties if set any"); - System.out.println("http.keepAlive.time.server:" + System.getProperty("http.keepAlive.time.server")); - System.out.println("http.keepAlive.time.proxy:" + System.getProperty("http.keepAlive.time.proxy")); - System.setProperty("java.net.useSystemProxies", "false"); - System.out.println("http.proxyPort:"+System.getProperty("http.proxyPort")); - System.out.println("http.proxyHost:"+System.getProperty("http.proxyHost")); - System.clearProperty("http.keepAlive.time.server"); - System.clearProperty("http.keepAlive.time.proxy"); - // fetch clientScenearios for each scenarioNumber from array and set it to - // System property. - if (!clientScenarios[getClientScenarioNumber(scenarioNumber)].equalsIgnoreCase(NI)) { - System.out.println("Client Input Parsing"); - for (String clientScenarioString : clientScenarios[getClientScenarioNumber(scenarioNumber)].split(CLIENT_SEPARATOR)) { - System.out.println(clientScenarioString); - String key = clientScenarioString.split("=")[0]; - String value = clientScenarioString.split("=")[1]; - System.setProperty(key, value); + if (httpClientCached != null) { + System.out.println("KeepingAlive:" + httpClientCached.isKeepingAlive()); + System.out.println("UsingProxy:" + httpClientCached.getUsingProxy()); + System.out.println("ProxiedHost:" + httpClientCached.getProxyHostUsed()); + System.out.println("ProxiedPort:" + httpClientCached.getProxyPortUsed()); + Class clientVectorClass = Class.forName("sun.net.www.http.ClientVector"); + Field napField = clientVectorClass.getDeclaredField("nap"); + napField.setAccessible(true); + int napValue = (int) napField.get(clientVectorObjectInMap); + int actualValue = napValue / 1000; + if (expectedValue == actualValue) { + System.out.printf("Cache time:%d\n", actualValue); + } else { + throw new RuntimeException("Sleep time of " + actualValue + " not expected (" + expectedValue + ")"); + } + } else { + if (expectedValue == 0) { + System.out.println("Connection not cached."); + } else { + throw new RuntimeException("Connection was not cached although expected with sleep time of:" + expectedValue); } } + } + + private void connectToServerURL(int expectedValue) throws Exception { // wait until ServerSocket moves to listening state. - this.serverCountDownLatch.await(); - System.out.println("client started"); - URL url = URIBuilder.newBuilder().scheme("http").loopback().port(SERVER_PORT).toURL(); - System.out.println("connecting from client to SERVER URL:" + url); + serverGate.arriveAndAwaitAdvance(); + URL url = URIBuilder.newBuilder().scheme("http").loopback().port(serverPort).toURL(); + System.out.println("connecting to server URL: " + url + ", isProxySet: " + isProxySet); HttpURLConnection httpUrlConnection = null; - /* - * isProxySet is set to true when Expected Server Response contains Proxy-Connection header. - */ + + // isProxySet is set to true when Expected Server Response contains Proxy-Connection header. if (isProxySet) { - httpUrlConnection = (sun.net.www.protocol.http.HttpURLConnection) url - .openConnection(new Proxy(Type.HTTP, new InetSocketAddress("localhost", SERVER_PORT))); + httpUrlConnection = (HttpURLConnection) url + .openConnection(new Proxy(Type.HTTP, new InetSocketAddress("localhost", serverPort))); } else { - httpUrlConnection = (sun.net.www.protocol.http.HttpURLConnection) url.openConnection(); + httpUrlConnection = (HttpURLConnection) url.openConnection(); } - InputStreamReader inputStreamReader = new InputStreamReader(httpUrlConnection.getInputStream()); - BufferedReader bufferedReader = null; - try { - bufferedReader = new BufferedReader(inputStreamReader); + + try (InputStreamReader inputStreamReader = new InputStreamReader(httpUrlConnection.getInputStream()); + BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) { while (true) { - String eachLine = bufferedReader.readLine(); - if (eachLine == null) { + String line = bufferedReader.readLine(); + if (line == null) { break; } - System.out.println(eachLine); - } - } finally { - if (bufferedReader != null) { - bufferedReader.close(); + System.out.println(line); } } - // System.out.println("ResponseCode:" + httpUrlConnection.getResponseCode()); - // System.out.println("ResponseMessage:" + httpUrlConnection.getResponseMessage()); - // System.out.println("Content:" + httpUrlConnection.getContent()); - // Thread.sleep(2000); for (Entry> header : httpUrlConnection.getHeaderFields().entrySet()) { System.out.println(header.getKey() + "=" + header.getValue()); } - fetchInfo(scenarioNumber, httpUrlConnection); + fetchInfo(expectedValue, httpUrlConnection); } - private void fetchInfo(int scenarioNumber, sun.net.www.protocol.http.HttpURLConnection httpUrlConnection) - throws Exception { - Field field = Class.forName("sun.net.www.protocol.http.HttpURLConnection").getDeclaredField("http"); - field.setAccessible(true); - HttpClient httpClient = (HttpClient) field.get(httpUrlConnection); - // System.out.println("httpclient=" + httpClient); - Field keepAliveField = Class.forName("sun.net.www.http.HttpClient").getDeclaredField("kac"); - keepAliveField.setAccessible(true); - KeepAliveCache keepAliveCache = (KeepAliveCache) keepAliveField.get(httpClient); - System.out.println("keepAliveCache" + keepAliveCache); - System.out.println("SERVER URL:" + httpUrlConnection.getURL()); - /* - * create KeepAliveKey(URL,Object) object and compare created KeepAliveKey and - * existing using equals() method: KeepAliveKey.equals() - */ - Class keepAliveKeyClass = Class.forName("sun.net.www.http.KeepAliveKey"); - // System.out.println("keepAliveKeyClass=" + keepAliveKeyClass); - Constructor keepAliveKeyClassconstructor = keepAliveKeyClass.getDeclaredConstructors()[0]; - keepAliveKeyClassconstructor.setAccessible(true); - Object expectedKeepAliveKey = keepAliveKeyClassconstructor.newInstance(httpUrlConnection.getURL(), null); - System.out.println("ExpectedKeepAliveKey=" + expectedKeepAliveKey); - Object clientVectorObjectInMap = keepAliveCache.get(expectedKeepAliveKey); - System.out.println("ClientVector=" + clientVectorObjectInMap); - HttpClient httpClientCached = keepAliveCache.get(httpUrlConnection.getURL(), null); - System.out.println("HttpClient in Cache:" + httpClientCached); - if(httpClientCached != null) { - System.out.println("KeepingAlive:" + httpClientCached.isKeepingAlive()); - System.out.println("UsingProxy:" + httpClientCached.getUsingProxy()); - System.out.println("ProxiedHost:" + httpClientCached.getProxyHostUsed()); - System.out.println("ProxiedPort:" + httpClientCached.getProxyPortUsed()); - System.out.println("ProxyPortUsingSystemProperty:" + System.getProperty("http.proxyPort")); - System.out.println("ProxyHostUsingSystemProperty:" + System.getProperty("http.proxyHost")); - System.out.println("http.keepAlive.time.server=" + System.getProperty("http.keepAlive.time.server")); - System.out.println("http.keepAlive.time.proxy=" + System.getProperty("http.keepAlive.time.proxy")); - Class clientVectorClass = Class.forName("sun.net.www.http.ClientVector"); - // System.out.println("clientVectorClass=" + clientVectorClass); - Field napField = clientVectorClass.getDeclaredField("nap"); - napField.setAccessible(true); - int napValue = (int) napField.get(clientVectorObjectInMap); - int actualValue = napValue / 1000; - // System.out.println("nap=" + napValue / 1000); - System.out.printf("ExpectedOutput:%d ActualOutput:%d ", expectedValues[scenarioNumber], actualValue); - System.out.println(); - if (expectedValues[scenarioNumber] != actualValue) { - throw new RuntimeException( - "ExpectedOutput:" + expectedValues[scenarioNumber] + " ActualOutput: " + actualValue); + private int getExpectedCachingValue(int serverScenario) { + if (serverScenario == 2) { + // Connection: keep-alive && Keep-alive: timeout=20 + // + // server side keep-alive timeout is what counts here + return 20; + } else if (serverScenario == 3 || serverScenario == 4 || serverScenario == 8) { + // Proxy-Connection: keep-alive + // Connection:keep-alive && Proxy-connection:keep-alive + // Proxy-Connection:keep-alive && Keep-alive:timeout=-20 + // + // Proxy-connection:keep-alive is set, timeout could be invalid -> value of http.keepAlive.time.proxy or default of 60 + int httpKeepAliveTimeProxy; + try { + httpKeepAliveTimeProxy = Integer.valueOf(System.getProperty("http.keepAlive.time.proxy")); + } catch (NumberFormatException e) { + httpKeepAliveTimeProxy = -1; } + return httpKeepAliveTimeProxy < 0 ? 60 : httpKeepAliveTimeProxy; + } else if (serverScenario == 5) { + // Proxy-connection:keep-alive && Keep-alive:timeout=120 + // + // server side keep-alive timeout is what counts here + return 120; + } else if (serverScenario == 7 || serverScenario == 9) { + // Connection: keep-alive && Keep-alive: timeout=0 + // Proxy-Connection:keep-alive && Keep-alive:timeout=0 + // + // no caching + return 0; } else { - //executed when value is not cached. - String expected = expectedValues[scenarioNumber] == 0 ? NOT_CACHED - : String.valueOf(expectedValues[scenarioNumber]); - System.out.println("ExpectedOutput:" + expected + " ActualOutput:" + NOT_CACHED); - if (!expected.equalsIgnoreCase(NOT_CACHED)) { - throw new RuntimeException("ExpectedOutput:" + expected + " ActualOutput:" + NOT_CACHED); + // No server parameters + // Connection: keep-alive + // Connection: keep-alive && Keep-alive: timeout=-20 + // + // Nothing or Connection:keep-alive is set, timeout could be invalid -> value of http.keepAlive.time.server or default of 5 + int httpKeepAliveTimeServer; + try { + httpKeepAliveTimeServer = Integer.valueOf(System.getProperty("http.keepAlive.time.server")); + } catch (NumberFormatException e) { + httpKeepAliveTimeServer = -1; } - } + return httpKeepAliveTimeServer < 0 ? 5 : httpKeepAliveTimeServer; + } } - public static void main(String[] args) throws Exception { - if (args.length != 1) { - throw new IllegalArgumentException("Usage:java KeepAliveTest.java "); + private void runScenario(int scenarioNumber) throws Exception { + int expectedValue = getExpectedCachingValue(scenarioNumber); + System.out.println("Expecting Cache Time of " + expectedValue + " for server headers:"); + if (serverHeaders[scenarioNumber] == null) { + System.out.println(); + } else { + System.out.print(serverHeaders[scenarioNumber]); } + Thread server = new Thread(() -> executeServer(scenarioNumber)); + server.start(); + connectToServerURL(expectedValue); + server.join(); + System.out.println(); + } + + private static void initialize() throws Exception { + System.clearProperty("http.proxyPort"); + System.clearProperty("http.proxyHost"); + System.setProperty("java.net.useSystemProxies", "false"); + + Field keepAliveField = sun.net.www.http.HttpClient.class.getDeclaredField("kac"); + keepAliveField.setAccessible(true); + keepAliveCache = (KeepAliveCache) keepAliveField.get(null); + System.out.println("KeepAliveCache: " + keepAliveCache); + keepAliveKeyClassconstructor = Class.forName("sun.net.www.http.KeepAliveKey").getDeclaredConstructors()[0]; + keepAliveKeyClassconstructor.setAccessible(true); + logger.setLevel(Level.FINEST); ConsoleHandler h = new ConsoleHandler(); h.setLevel(Level.FINEST); logger.addHandler(h); - KeepAliveTest keepAliveTest = new KeepAliveTest(); - if (args.length != 0) { - keepAliveTest.startScenario(Integer.valueOf(args[0])); + + System.out.println("Client properties: http.keepAlive.time.server=" + System.getProperty("http.keepAlive.time.server") + + ", http.keepAlive.time.proxy=" + System.getProperty("http.keepAlive.time.proxy")); + } + + public static void main(String[] args) throws Exception { + if (args.length > 1) { + throw new IllegalArgumentException("Usage:java KeepAliveTest.java "); + } else if (args.length == 1) { + // an individual test scenario + try { + int scenarioNumber = Integer.valueOf(args[0]); + if (scenarioNumber < 0 || scenarioNumber > 9) { + throw new IllegalArgumentException("Scenario " + scenarioNumber + " does not exist"); + } + initialize(); + new KeepAliveTest().runScenario(scenarioNumber); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Scenario must be a number, got " + args[0]); + } + } else { + // all server scenarios + initialize(); + for (int i = 0; i < 10; i++) { + new KeepAliveTest().runScenario(i); + } } - // make main thread wait until server and client is completed. - keepAliveTest.countDownLatch.await(); } } diff --git a/test/jdk/sun/nio/ch/TestMaxCachedBufferSize.java b/test/jdk/sun/nio/ch/TestMaxCachedBufferSize.java index 4f2d2907673..ef73a15256a 100644 --- a/test/jdk/sun/nio/ch/TestMaxCachedBufferSize.java +++ b/test/jdk/sun/nio/ch/TestMaxCachedBufferSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2021, 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 @@ -22,39 +22,39 @@ */ import java.io.IOException; - import java.lang.management.BufferPoolMXBean; import java.lang.management.ManagementFactory; - import java.nio.ByteBuffer; - import java.nio.channels.FileChannel; - import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; +import java.util.SplittableRandom; +import java.util.concurrent.CountDownLatch; import static java.nio.file.StandardOpenOption.CREATE; import static java.nio.file.StandardOpenOption.TRUNCATE_EXISTING; import static java.nio.file.StandardOpenOption.WRITE; -import java.util.List; -import java.util.Random; -import java.util.concurrent.CountDownLatch; +import jdk.test.lib.RandomFactory; /* * @test * @requires sun.arch.data.model == "64" * @modules java.management + * @library /test/lib * @build TestMaxCachedBufferSize - * @run main/othervm TestMaxCachedBufferSize - * @run main/othervm -Djdk.nio.maxCachedBufferSize=0 TestMaxCachedBufferSize - * @run main/othervm -Djdk.nio.maxCachedBufferSize=2000 TestMaxCachedBufferSize - * @run main/othervm -Djdk.nio.maxCachedBufferSize=100000 TestMaxCachedBufferSize - * @run main/othervm -Djdk.nio.maxCachedBufferSize=10000000 TestMaxCachedBufferSize - * @summary Test the implementation of the jdk.nio.maxCachedBufferSize property. + * @run main/othervm/timeout=150 TestMaxCachedBufferSize + * @run main/othervm/timeout=150 -Djdk.nio.maxCachedBufferSize=0 TestMaxCachedBufferSize + * @run main/othervm/timeout=150 -Djdk.nio.maxCachedBufferSize=2000 TestMaxCachedBufferSize + * @run main/othervm/timeout=150 -Djdk.nio.maxCachedBufferSize=100000 TestMaxCachedBufferSize + * @run main/othervm/timeout=150 -Djdk.nio.maxCachedBufferSize=10000000 TestMaxCachedBufferSize + * @summary Test the implementation of the jdk.nio.maxCachedBufferSize property + * (use -Dseed=X to set PRNG seed) + * @key randomness */ public class TestMaxCachedBufferSize { - private static final int DEFAULT_ITERS = 10 * 1000; + private static final int DEFAULT_ITERS = 5 * 1000; private static final int DEFAULT_THREAD_NUM = 4; private static final int SMALL_BUFFER_MIN_SIZE = 4 * 1024; @@ -70,7 +70,9 @@ public class TestMaxCachedBufferSize { private static final int LARGE_BUFFER_FREQUENCY = 100; private static final String FILE_NAME_PREFIX = "nio-out-file-"; - private static final int VERBOSE_PERIOD = 5 * 1000; + private static final int VERBOSE_PERIOD = DEFAULT_ITERS / 10; + + private static final SplittableRandom SRAND = RandomFactory.getSplittableRandom(); private static int iters = DEFAULT_ITERS; private static int threadNum = DEFAULT_THREAD_NUM; @@ -86,6 +88,8 @@ private static BufferPoolMXBean getDirectPool() { throw new Error("could not find direct pool"); } private static final BufferPoolMXBean directPool = getDirectPool(); + private static long initialCount; + private static long initialCapacity; // Each worker will do write operations on a file channel using // buffers of various sizes. The buffer size is randomly chosen to @@ -95,7 +99,7 @@ private static BufferPoolMXBean getDirectPool() { private static class Worker implements Runnable { private final int id; private final CountDownLatch finishLatch, exitLatch; - private final Random random = new Random(); + private SplittableRandom random = SRAND.split(); private long smallBufferCount = 0; private long largeBufferCount = 0; @@ -177,8 +181,9 @@ public Worker(int id, CountDownLatch finishLatch, CountDownLatch exitLatch) { } public static void checkDirectBuffers(long expectedCount, long expectedMax) { - final long directCount = directPool.getCount(); - final long directTotalCapacity = directPool.getTotalCapacity(); + final long directCount = directPool.getCount() - initialCount; + final long directTotalCapacity = + directPool.getTotalCapacity() - initialCapacity; System.out.printf("Direct %d / %dK\n", directCount, directTotalCapacity / 1024); @@ -190,12 +195,15 @@ public static void checkDirectBuffers(long expectedCount, long expectedMax) { if (directTotalCapacity > expectedMax) { throw new Error(String.format( - "inconsistent direct buffer total capacity, expectex max = %d, found = %d", + "inconsistent direct buffer total capacity, expected max = %d, found = %d", expectedMax, directTotalCapacity)); } } public static void main(String[] args) { + initialCount = directPool.getCount(); + initialCapacity = directPool.getTotalCapacity(); + final String maxBufferSizeStr = System.getProperty("jdk.nio.maxCachedBufferSize"); final long maxBufferSize = (maxBufferSizeStr != null) ? Long.valueOf(maxBufferSizeStr) : Long.MAX_VALUE; diff --git a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java index 3c4a50c03ed..a0e02b32319 100644 --- a/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java +++ b/test/jdk/sun/security/lib/cacerts/VerifyCACerts.java @@ -19,17 +19,16 @@ * 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 8189131 8198240 8191844 8189949 8191031 8196141 8204923 8195774 8199779 * 8209452 8209506 8210432 8195793 8216577 8222089 8222133 8222137 8222136 * 8223499 8225392 8232019 8234245 8233223 8225068 8225069 8243321 8243320 * 8243559 8225072 8258630 8259312 8256421 8225081 8225082 8225083 8245654 * 8305975 8304760 8307134 8295894 8314960 8317373 8317374 8318759 8319187 - * 8321408 8316138 + * 8321408 8316138 8341057 * @summary Check root CA entries in cacerts file */ import java.io.ByteArrayInputStream; @@ -48,12 +47,12 @@ public class VerifyCACerts { + File.separator + "security" + File.separator + "cacerts"; // The numbers of certs now. - private static final int COUNT = 110; + private static final int COUNT = 112; // SHA-256 of cacerts, can be generated with // shasum -a 256 cacerts | sed -e 's/../&:/g' | tr '[:lower:]' '[:upper:]' | cut -c1-95 private static final String CHECKSUM - = "C1:68:B4:AC:51:BF:B5:C6:FD:20:69:17:E1:AF:E4:5B:01:9B:AA:3F:C3:9A:80:A8:51:53:74:2C:A2:04:B0:FF"; + = "8F:E0:6F:7F:21:59:33:A6:43:F3:48:FD:A3:4A:8E:28:35:AA:DD:6E:A5:43:56:F1:28:34:48:DF:5C:D2:7C:72"; // map of cert alias to SHA-256 fingerprint @SuppressWarnings("serial") @@ -279,6 +278,10 @@ public class VerifyCACerts { "4F:A3:12:6D:8D:3A:11:D1:C4:85:5A:4F:80:7C:BA:D6:CF:91:9D:3A:5A:88:B0:3B:EA:2C:63:72:D9:3C:40:C9"); put("globalsigne46 [jdk]", "CB:B9:C4:4D:84:B8:04:3E:10:50:EA:31:A6:9F:51:49:55:D7:BF:D2:E2:C6:B4:93:01:01:9A:D6:1D:9F:50:58"); + put("ssltlsrootecc2022 [jdk]", + "C3:2F:FD:9F:46:F9:36:D1:6C:36:73:99:09:59:43:4B:9A:D6:0A:AF:BB:9E:7C:F3:36:54:F1:44:CC:1B:A1:43"); + put("ssltlsrootrsa2022 [jdk]", + "8F:AF:7D:2E:2C:B4:70:9B:B8:E0:B3:36:66:BF:75:A5:DD:45:B5:DE:48:0F:8E:A8:D4:BF:E6:BE:BC:17:F2:ED"); } }; diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/Distrust.java b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/Distrust.java new file mode 100644 index 00000000000..1c1fcee3609 --- /dev/null +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/Distrust.java @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2024, 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.*; +import java.math.BigInteger; +import java.security.*; +import java.security.cert.*; +import java.time.*; +import java.util.*; +import javax.net.ssl.*; +import sun.security.validator.Validator; +import sun.security.validator.ValidatorException; + +import jdk.test.lib.security.SecurityUtils; + +/** + * @test + * @bug 8337664 8341059 + * @summary Check that TLS Server certificates chaining back to distrusted + * Entrust roots are invalid + * @library /test/lib + * @modules java.base/sun.security.validator + * @run main/othervm Distrust after policyOn invalid + * @run main/othervm Distrust after policyOff valid + * @run main/othervm Distrust before policyOn valid + * @run main/othervm Distrust before policyOff valid + */ + +public class Distrust { + + private static final String TEST_SRC = System.getProperty("test.src", "."); + private static CertificateFactory cf; + + // Each of the roots have a test certificate chain stored in a file + // named "-chain.pem". + private static String[] rootsToTest = new String[] { + "entrustevca", "entrustrootcaec1", "entrustrootcag2", "entrustrootcag4", + "entrust2048ca", "affirmtrustcommercialca", "affirmtrustnetworkingca", + "affirmtrustpremiumca", "affirmtrustpremiumeccca" }; + + // A date that is after the restrictions take effect + private static final Date NOVEMBER_12_2024 = + Date.from(LocalDate.of(2024, 11, 12) + .atStartOfDay(ZoneOffset.UTC) + .toInstant()); + + // A date that is a second before the restrictions take effect + private static final Date BEFORE_NOVEMBER_12_2024 = + Date.from(LocalDate.of(2024, 11, 12) + .atStartOfDay(ZoneOffset.UTC) + .minusSeconds(1) + .toInstant()); + + public static void main(String[] args) throws Exception { + + cf = CertificateFactory.getInstance("X.509"); + + boolean before = args[0].equals("before"); + boolean policyOn = args[1].equals("policyOn"); + boolean isValid = args[2].equals("valid"); + + if (!policyOn) { + // disable policy (default is on) + Security.setProperty("jdk.security.caDistrustPolicies", ""); + } + + Date notBefore = before ? BEFORE_NOVEMBER_12_2024 : NOVEMBER_12_2024; + + X509TrustManager pkixTM = getTMF("PKIX", null); + X509TrustManager sunX509TM = getTMF("SunX509", null); + for (String test : rootsToTest) { + System.err.println("Testing " + test); + X509Certificate[] chain = loadCertificateChain(test); + + testTM(sunX509TM, chain, notBefore, isValid); + testTM(pkixTM, chain, notBefore, isValid); + } + } + + private static X509TrustManager getTMF(String type, + PKIXBuilderParameters params) throws Exception { + TrustManagerFactory tmf = TrustManagerFactory.getInstance(type); + if (params == null) { + tmf.init((KeyStore)null); + } else { + tmf.init(new CertPathTrustManagerParameters(params)); + } + TrustManager[] tms = tmf.getTrustManagers(); + for (TrustManager tm : tms) { + X509TrustManager xtm = (X509TrustManager)tm; + return xtm; + } + throw new Exception("No TrustManager for " + type); + } + + private static PKIXBuilderParameters getParams() throws Exception { + PKIXBuilderParameters pbp = + new PKIXBuilderParameters(SecurityUtils.getCacertsKeyStore(), + new X509CertSelector()); + pbp.setRevocationEnabled(false); + return pbp; + } + + private static void testTM(X509TrustManager xtm, X509Certificate[] chain, + Date notBefore, boolean valid) throws Exception { + // Check if TLS Server certificate (the first element of the chain) + // is issued after the specified notBefore date (should be rejected + // unless distrust property is false). To do this, we need to + // fake the notBefore date since none of the test certs are issued + // after then. + chain[0] = new DistrustedTLSServerCert(chain[0], notBefore); + + try { + xtm.checkServerTrusted(chain, "ECDHE_RSA"); + if (!valid) { + throw new Exception("chain should be invalid"); + } + } catch (CertificateException ce) { + // expired TLS certificates should not be treated as failure + if (expired(ce)) { + System.err.println("Test is N/A, chain is expired"); + return; + } + if (valid) { + throw new Exception("Unexpected exception, chain " + + "should be valid", ce); + } + if (ce instanceof ValidatorException) { + ValidatorException ve = (ValidatorException)ce; + if (ve.getErrorType() != ValidatorException.T_UNTRUSTED_CERT) { + ce.printStackTrace(System.err); + throw new Exception("Unexpected exception: " + ce); + } + } else { + throw new Exception("Unexpected exception: " + ce); + } + } + } + + // check if a cause of exception is an expired cert + private static boolean expired(CertificateException ce) { + if (ce instanceof CertificateExpiredException) { + return true; + } + Throwable t = ce.getCause(); + while (t != null) { + if (t instanceof CertificateExpiredException) { + return true; + } + t = t.getCause(); + } + return false; + } + + private static X509Certificate[] loadCertificateChain(String name) + throws Exception { + try (InputStream in = new FileInputStream(TEST_SRC + File.separator + + name + "-chain.pem")) { + Collection certs = + (Collection)cf.generateCertificates(in); + return certs.toArray(new X509Certificate[0]); + } + } + + private static class DistrustedTLSServerCert extends X509Certificate { + private final X509Certificate cert; + private final Date notBefore; + DistrustedTLSServerCert(X509Certificate cert, Date notBefore) { + this.cert = cert; + this.notBefore = notBefore; + } + public Set getCriticalExtensionOIDs() { + return cert.getCriticalExtensionOIDs(); + } + public byte[] getExtensionValue(String oid) { + return cert.getExtensionValue(oid); + } + public Set getNonCriticalExtensionOIDs() { + return cert.getNonCriticalExtensionOIDs(); + } + public boolean hasUnsupportedCriticalExtension() { + return cert.hasUnsupportedCriticalExtension(); + } + public void checkValidity() throws CertificateExpiredException, + CertificateNotYetValidException { + // always pass + } + public void checkValidity(Date date) throws CertificateExpiredException, + CertificateNotYetValidException { + // always pass + } + public int getVersion() { return cert.getVersion(); } + public BigInteger getSerialNumber() { return cert.getSerialNumber(); } + public Principal getIssuerDN() { return cert.getIssuerDN(); } + public Principal getSubjectDN() { return cert.getSubjectDN(); } + public Date getNotBefore() { return notBefore; } + public Date getNotAfter() { return cert.getNotAfter(); } + public byte[] getTBSCertificate() throws CertificateEncodingException { + return cert.getTBSCertificate(); + } + public byte[] getSignature() { return cert.getSignature(); } + public String getSigAlgName() { return cert.getSigAlgName(); } + public String getSigAlgOID() { return cert.getSigAlgOID(); } + public byte[] getSigAlgParams() { return cert.getSigAlgParams(); } + public boolean[] getIssuerUniqueID() { + return cert.getIssuerUniqueID(); + } + public boolean[] getSubjectUniqueID() { + return cert.getSubjectUniqueID(); + } + public boolean[] getKeyUsage() { return cert.getKeyUsage(); } + public int getBasicConstraints() { return cert.getBasicConstraints(); } + public byte[] getEncoded() throws CertificateEncodingException { + return cert.getEncoded(); + } + public void verify(PublicKey key) throws CertificateException, + InvalidKeyException, NoSuchAlgorithmException, + NoSuchProviderException, SignatureException { + cert.verify(key); + } + public void verify(PublicKey key, String sigProvider) throws + CertificateException, InvalidKeyException, NoSuchAlgorithmException, + NoSuchProviderException, SignatureException { + cert.verify(key, sigProvider); + } + public PublicKey getPublicKey() { return cert.getPublicKey(); } + public String toString() { return cert.toString(); } + } +} diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustcommercialca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustcommercialca-chain.pem new file mode 100644 index 00000000000..76aa6d14338 --- /dev/null +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustcommercialca-chain.pem @@ -0,0 +1,77 @@ +Root Certificate: + Version: 3 (0x2) + Serial Number: 8608355977964138876 (0x7777062726a9b17c) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Commercial + Validity + Not Before: Jan 29 14:06:06 2010 GMT + Not After : Dec 31 14:06:06 2030 GMT + +-----BEGIN CERTIFICATE----- +MIIHHjCCBgagAwIBAgIQAWZjFOyCvT00u/gtkCvS2TANBgkqhkiG9w0BAQsFADCB +gzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJT +ZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhBZmZp +cm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYxMB4XDTI0MDYyODIx +MzgwNVoXDTI1MDcyODIxMzgwNFowgdgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdP +bnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEzARBgsrBgEEAYI3PAIBAxMCQ0ExGDAW +BgsrBgEEAYI3PAIBAhMHT250YXJpbzEcMBoGA1UEChMTQWZmaXJtdHJ1c3QgTGlt +aXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzI1 +NDA1NDcxKDAmBgNVBAMTH3ZhbGlkY29tbWVyY2lhbC5hZmZpcm10cnVzdC5jb20w +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDeIT2XO0hJ5wDSbIiIcMvs +P3NpQc7O7v5DqldpME6+Qn2sF5b9hc6j72hgTXREa77uUcP5u1JcMWCSWwYQHMpJ +kFzmIzijhS60wW1epb5QyTgM3ZYh1WKvttFCbHUcrTtd+LoPFYsjw9ZK//K9tPp+ +ddn06/ivWvUO5y5vn0wrCaB9tuLdDn4RCQzK2XoZdDuqhPlBBogJX0vM6lsXjgLy +EbvE+/sKYps/In6VtRvCoYavg3OqaIMeaA7gTiYTb1ZGFOAiltnq7fcp6SZUohK3 +QNihv1DadVc+n8LnEUKKDkgG2YgWEFczaE3qwG3ef6L3MzLGrkgVY+qGHyyv2IE7 +AgMBAAGjggM1MIIDMTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBT4ARNL47hAsOpa +96VMgKEY3sLIAjAfBgNVHSMEGDAWgBTb72U3C+VHyzXRkB8DwbyIx6fqgDBsBggr +BgEFBQcBAQRgMF4wJwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLmFmZmlybXRydXN0 +LmNvbTAzBggrBgEFBQcwAoYnaHR0cDovL2FpYS5hZmZpcm10cnVzdC5jb20vYWZ0 +ZXYxY2EuY3J0MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuYWZmaXJtdHJ1 +c3QuY29tL2NybC9hZnRldjFjYS5jcmwwKgYDVR0RBCMwIYIfdmFsaWRjb21tZXJj +aWFsLmFmZmlybXRydXN0LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI +KwYBBQUHAwEGCCsGAQUFBwMCMFYGA1UdIARPME0wBwYFZ4EMAQEwQgYKKwYBBAGC +jwkCATA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5hZmZpcm10cnVzdC5jb20v +cmVwb3NpdG9yeTCCAYAGCisGAQQB1nkCBAIEggFwBIIBbAFqAHcAEvFONL1TckyE +BhnDjz96E/jntWKHiJxtMAWE6+WGJjoAAAGQYMi3wQAABAMASDBGAiEAjvdsU4G2 +o4BZSOOjaH6gOp7zhKtXQByQUvfHfsi2ePcCIQDnnIO2qlHBm+sskUDlXfR0lCUW +yFPVr9nFZ0L9YPpozgB2AA3h8jAr0w3BQGISCepVLvxHdHyx1+kw7w5CHrR+Tqo0 +AAABkGDIt9MAAAQDAEcwRQIhANh1zS3Qeo9yKF+j3G52JhmDRYBS+1TM0wykoXCY +llpxAiAG+LAlKSbwwgrboUSTDDXWNeoRYZ7fKbU72kKfHrpZvwB3ABoE/0nQVB1A +r/agw7/x2MRnL07s7iNAaJhrF0Au3Il9AAABkGDIt9sAAAQDAEgwRgIhAN8OoC4I +zw8bFJy8ACgK40c9ZfsIfFhePTc9CyrL5uDsAiEA4Jn/IqBB9L5DeTgqw9hBaYag +FmY/2gWDip36ga0WUsAwDQYJKoZIhvcNAQELBQADggEBABywPLJP097Emz6LNeFU +/HvfhaUKv2pgIHf/Kvjs5x78RK9G605THPEHr/TeUjNZ4PBd48WBNVWzyd/8FuOt +r+FsYkRJb9CnrOhZHuCwlcdWXvuY8PiuBmT+xB16BWR5yhYbbiGe4hea0Pf6CfHh +jJoGJw4dQKfgneZOV7IcaWnNTKYawlcZOgxvEwFvj+iZM31WphEPKRAV+N+Tp+ZR +nxlEdjmdbOjqBydlYIEzuFIgxgtnPdK5wqCOWb+z2cARUAO/AkiWrOLTPDc7ydQK +GcfDrSqffHOlwaee08C6STFaJWIcpqxZdXE6Jc+8/85bfPEAG1UepgfnBTqW9RGT +Q3s= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEqDCCA5CgAwIBAgIQFylVHtaOf7Ht9XMA811/1TANBgkqhkiG9w0BAQsFADBE +MQswCQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxHzAdBgNVBAMMFkFm +ZmlybVRydXN0IENvbW1lcmNpYWwwHhcNMTkwMzIxMjAyNzU0WhcNMzAxMjAyMDQw +MDAwWjCBgzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYD +VQQLEyJTZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQD +EyhBZmZpcm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYxMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuPBMIa9VuXJGAw0MHvieGciPFA11 +b9T49YJ7T+zVpoMMQO+ueUKVHb2l26oeCiwIhXMQ5LquOVcx+rofouzcKXY3wKDZ +zHIOnAkU+23Ucn/3dRH7aHJULsBufZq+NvwgYSgJJEDKfqvIV/c5HiRyZ2H+nAI5 +10Q2xC0UxgSBsufccQ+Fwkg6BAGDlTXrvi8wi75UaGue6jv/qcKLybeVUrgqKE64 +d9oa9PG5/g89QwSdsIQEdVSFzFvFpOG9YhJbJ177Zg6DGCxU0lWwFrVpyH/2vnXl +jhMQScn8UxzCJdDg3EDqjgaV0JH2yoLug+QVYgURPu5BEb5ut9vAdP7cLwIDAQAB +o4IBVDCCAVAwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2Nz +cC5hZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFNvvZTcL5UfLNdGQHwPBvIjHp+qA +MBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUnZPGU4teyq8/nx4P5ZmV +vCT2lI8wRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8v +d3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MEkGA1UdHwRCMEAwPqA8oDqG +OGh0dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2NybC9BZmZpcm1UcnVzdENvbW1l +cmNpYWwuY3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +KwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAATH11fMrINGmQGQqQW0ATteVnUG +LrmRSN2OlmRm+dkUwKXhcQQEfYYlEggPqgvxSUpw13fXSOqVHqAcj3BIqF957kh+ +m3DmC0RX9KaEKD165pf77P5nZcRmZpBl9cctvzIxN19uzcminchusYwLyeWhBtTZ +xpER9LbrfMNaQ7GnrgalMx54QvdjOhw/GJs9/SqEzYmPshL+DzgZX/oAzY63rQIh +rBblf6/2talZqci96oFzNst8rGfPy/xQ7lgkki1hwIYbORMfloBhP+vAZJo0mxdM +ipu3Z0ToK+KU2iqnBxXVr2/kod+CpkHnjUHa1wnQuSaefng3XwZ/vqtSL9c= +-----END CERTIFICATE----- diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustnetworkingca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustnetworkingca-chain.pem new file mode 100644 index 00000000000..7384d31152e --- /dev/null +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustnetworkingca-chain.pem @@ -0,0 +1,76 @@ +Root Certificate: + Version: 3 (0x2) + Serial Number: 8957382827206547757 (0x7c4f04391cd4992d) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Networking + Validity + Not Before: Jan 29 14:08:24 2010 GMT + Not After : Dec 31 14:08:24 2030 GMT + +-----BEGIN CERTIFICATE----- +MIIHGjCCBgKgAwIBAgIQX2vGPaCJ1tS0ncp2OlBMFjANBgkqhkiG9w0BAQsFADCB +gzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJT +ZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhBZmZp +cm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYzMB4XDTI0MDYyODIx +NDU0OVoXDTI1MDcyODIxNDU0OFowgdgxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdP +bnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEzARBgsrBgEEAYI3PAIBAxMCQ0ExGDAW +BgsrBgEEAYI3PAIBAhMHT250YXJpbzEcMBoGA1UEChMTQWZmaXJtdHJ1c3QgTGlt +aXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzI1 +NDA1NDcxKDAmBgNVBAMTH3ZhbGlkbmV0d29ya2luZy5hZmZpcm10cnVzdC5jb20w +ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCkGknE8kFr+CaIybQrDPRw +z9OKXq77p4CnrkF1/g9w/HiIs6Ps8YqTjsiTKM3wYLbvPA+TbO9DpCSyCP2bVyLf +AjUE617KZSpfy9RqzvGjn/1qH/cBKohhEliMfDj4ZHfY4x+1WYTZPVK/g0Ny5RAP +wz9lJHR2SsVGLvpqXzWaVoxifJ8HZWD7n5z/75WeYko+Hubx3WvzJZcN2Xjn+q6a +7wkDaXPayrvn5uWGPlOLQHqJ5z7wts21jASMTfJAToFyzH6dGwvqxkP3bVJGJ8AF +vtMfqVjcOcjWgmmOEHMPAAqs5QKrYuSLccH6hFTwFEUCdMwVqfloznt2sNUSBoKj +AgMBAAGjggMxMIIDLTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTrE0z4fRyx9P9M +0FfA6VgGkJiYVDAfBgNVHSMEGDAWgBR5HrHJF8cerLHHFNfD6H+8uVCbFTBsBggr +BgEFBQcBAQRgMF4wJwYIKwYBBQUHMAGGG2h0dHA6Ly9vY3NwLmFmZmlybXRydXN0 +LmNvbTAzBggrBgEFBQcwAoYnaHR0cDovL2FpYS5hZmZpcm10cnVzdC5jb20vYWZ0 +ZXYzY2EuY3J0MDwGA1UdHwQ1MDMwMaAvoC2GK2h0dHA6Ly9jcmwuYWZmaXJtdHJ1 +c3QuY29tL2NybC9hZnRldjNjYS5jcmwwKgYDVR0RBCMwIYIfdmFsaWRuZXR3b3Jr +aW5nLmFmZmlybXRydXN0LmNvbTAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYI +KwYBBQUHAwEGCCsGAQUFBwMCMFYGA1UdIARPME0wBwYFZ4EMAQEwQgYKKwYBBAGC +jwkCAjA0MDIGCCsGAQUFBwIBFiZodHRwczovL3d3dy5hZmZpcm10cnVzdC5jb20v +cmVwb3NpdG9yeTCCAXwGCisGAQQB1nkCBAIEggFsBIIBaAFmAHYADeHyMCvTDcFA +YhIJ6lUu/Ed0fLHX6TDvDkIetH5OqjQAAAGQYM/MjQAABAMARzBFAiBjnehs1mvh +5Xm3uXZ7Bq8gijwiXThwnLSYROQxnWrnbAIhALbgJG+PRZQfzTBbgM/zAwNsBjhe +F5iENnaajJCxzOhaAHUAEvFONL1TckyEBhnDjz96E/jntWKHiJxtMAWE6+WGJjoA +AAGQYM/MgQAABAMARjBEAiAsWOm1IIjaxQP9uaPI9tQmkiJPUOTrBTsTDO+jkgiG ++QIgVNhND82rsFGjrtAAHzzgCVzLDUM3zaHxnP/z3BNuO4QAdQAaBP9J0FQdQK/2 +oMO/8djEZy9O7O4jQGiYaxdALtyJfQAAAZBgz8zLAAAEAwBGMEQCIBIGxtjk7Lw8 +i+oggK7VrPMNTB632t321cwhEm517BbZAiBws3+uytwh59N6qGJUuSFQnOZNPOPj +eQnH2fSdT1J2sDANBgkqhkiG9w0BAQsFAAOCAQEAcSzitESRKlbcUvxvUB7FjK0I +CaBU1Nyu0xDFCoG2pmp7GASJz34wtPYfsiX5+j4hDh/noMcgk7WlD8pzgWYw15Rk ++5kTv2v4U85y/JFjzMOHbz64KjQdGebqhjvC/E/EXxK+AZf4H574/w7rbyJ30vFL +gNvPF9AxS1MuYIO55jXrHMByKnFoQZgPsmAY/x+n+OzMxWOdR18PupypCB5TyJZ8 +pQzwoxmX7qeZHiXyJ8jQUwe1qoQc2SbwfQxfwSPUPSJuQo90N+5nyQMe7vvPBM0Y +/CXaFpfPqh71D4C0Ey+0hYxSt99gYs4P9twUByjIlP0wTyhaoEpt3zw9DdZypQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIEqDCCA5CgAwIBAgIQNCSh7Pjwo1/nRrcBHEPoRDANBgkqhkiG9w0BAQsFADBE +MQswCQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxHzAdBgNVBAMMFkFm +ZmlybVRydXN0IE5ldHdvcmtpbmcwHhcNMTkwMzIxMjAzODU5WhcNMzAxMjAyMDQw +MDAwWjCBgzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYD +VQQLEyJTZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQD +EyhBZmZpcm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYzMIIBIjAN +BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmHDl/3xr1qiHoe0Rzb3AGLw56e9J +l2a3X59+PAfI5wGBHuK9Dl7XsyoH65X6QIC/rXyVpuNgKbbwIGHB+rCSplyHzGyC +WeM3LXa2q1US7VteeFDS959nxJVRFfwATR9xAK6YTUWQ/yWdw0dZSm0lQNmEMBwS +qi0ufWokiWXZUzWHOu7A6driCohu9sFDwe1INJUPH6uIlovmzGvG3UYbUSymJcjs +Ka0fXXX9zukco8exlOIKWRJSNLxKtSSPDVASrGLQ1xi3qkiLTKci3+jKMNDFf1vw +foZN99HhUcWKXfr2KlWfANdjTMlsTKCfuhfWl1OBVNHGRrACAQCXI/ji0wIDAQAB +o4IBVDCCAVAwNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2Nz +cC5hZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFHkesckXxx6ssccU18Pof7y5UJsV +MBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUBx/S55zawm6iQLSwelAQ +UHTEyL0wRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8v +d3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MEkGA1UdHwRCMEAwPqA8oDqG +OGh0dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2NybC9BZmZpcm1UcnVzdE5ldHdv +cmtpbmcuY3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYI +KwYBBQUHAwIwDQYJKoZIhvcNAQELBQADggEBAAhmE4I56hNpnWXQ2Si8a/TgQUZr +X5Jlv1LDvl3rkDyfEIHNZ8dth17SakJYJBWHExph/iIYjCJ9YmeyhghV5rPqT+wF +4yyE2ngenIusfnWT2bTpT9u2VZbCNeACE5XnN2UHSA0J9idPjfLuthViWEvSZZUh +DJ53bX+exO366nDY4AI7owIyhz8hdsWyhZ/0ST+eD+kbgd8osd+GdxzRmyKcfl84 +D1K1uff01T9w2dyUaZglQsFljkaO6xmeXZJsPnhwCp/HlMHWzhAneUQ7I9FZSOW+ +WiYbt4RitmBpysadBReikWM4knECzJQ/fMT9vC0k9BLlqUYRwCH9vr0UnZo= +-----END CERTIFICATE----- diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumca-chain.pem new file mode 100644 index 00000000000..6f108bc1229 --- /dev/null +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumca-chain.pem @@ -0,0 +1,88 @@ +Root Certificate: + Version: 3 (0x2) + Serial Number: 7893706540734352110 (0x6d8c1446b1a60aee) + Signature Algorithm: sha384WithRSAEncryption + Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Premium + Validity + Not Before: Jan 29 14:10:36 2010 GMT + Not After : Dec 31 14:10:36 2040 GMT + +-----BEGIN CERTIFICATE----- +MIIIFjCCBv6gAwIBAgIQQVOTWr7tEAJXmRDkCSxkajANBgkqhkiG9w0BAQsFADCB +gzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJT +ZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhBZmZp +cm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYyMB4XDTI0MDYyODIx +NDgyN1oXDTI1MDcyODIxNDgyNlowgdUxCzAJBgNVBAYTAkNBMRAwDgYDVQQIEwdP +bnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExEzARBgsrBgEEAYI3PAIBAxMCQ0ExGDAW +BgsrBgEEAYI3PAIBAhMHT250YXJpbzEcMBoGA1UEChMTQWZmaXJtdHJ1c3QgTGlt +aXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzI1 +NDA1NDcxJTAjBgNVBAMTHHZhbGlkcHJlbWl1bS5hZmZpcm10cnVzdC5jb20wggIi +MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDVRMzwbDq47ivHOKqJdiEJNL2+ +g9Snj/BRctqcQTrIV99RP0pmAh5fHg7vnhVsHqc9sRLVcQWTJk9NuRJ2VnDKWsBa +Xrp5UWaNjS0vaFA4jzCi1gWzTTZgPTQn3VRG3JP1F5CZb405/mtWDaw/CfWkcUqQ +VSilqFlJRsjcPCzQh7ZaXAo+FmzJxNSwjxdP6JSYMeTDRCUpSb3T8PypVI1CEmLZ +jsxrg5oIZn25591g/pzgLE56N0stNY4d3q4YD1t5x46RsqYAJYSkk8rcTN+kHzsY +VSqaRDyPkGbmuCeJUvW24wJ30yQtXQWA+U0dMYLe7LyglJ7dkOzvWNbqrIcvM8My +hxH/wwVH7e4dL/1E58yr1BHENUk7Mp9rzIXj496eLkF5G1lMkNnuVRQqCAOW0rPY +V0rI8yrCMTK52s4mNjQo2J7JOYdTUvAWZ92MKvEjjhQlMH8eK72Km/+mkxpsgGmr +3c6u+Gom7oI5VaLZ+3p2uWaOsutk1tkzWjhzY4L27hwmIdWujfrWMRx8uxcfoJxX +gQ40d1QiSN51BtCPE5UnpLU/YUxMdzWmtUoGUfYIGVqDVToBnunIFMdmFjC0IrNl +hquDQi/OGMpzuOvxX1FoXb+rRwOhhdrcR0BQqUVRTV0U5LlcsDeNMqmqPE9mzGtJ +W69Fsh7crntng/L72wIDAQABo4IDMDCCAywwDAYDVR0TAQH/BAIwADAdBgNVHQ4E +FgQU3PWyi/4usZghgahc/Tj+Q60QLOcwHwYDVR0jBBgwFoAUc3yaOGg8UXxBCP6h +HyoetGHbzTwwbAYIKwYBBQUHAQEEYDBeMCcGCCsGAQUFBzABhhtodHRwOi8vb2Nz +cC5hZmZpcm10cnVzdC5jb20wMwYIKwYBBQUHMAKGJ2h0dHA6Ly9haWEuYWZmaXJt +dHJ1c3QuY29tL2FmdGV2MmNhLmNydDA8BgNVHR8ENTAzMDGgL6AthitodHRwOi8v +Y3JsLmFmZmlybXRydXN0LmNvbS9jcmwvYWZ0ZXYyY2EuY3JsMCcGA1UdEQQgMB6C +HHZhbGlkcHJlbWl1bS5hZmZpcm10cnVzdC5jb20wDgYDVR0PAQH/BAQDAgWgMB0G +A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjBWBgNVHSAETzBNMAcGBWeBDAEB +MEIGCisGAQQBgo8JAgMwNDAyBggrBgEFBQcCARYmaHR0cHM6Ly93d3cuYWZmaXJt +dHJ1c3QuY29tL3JlcG9zaXRvcnkwggF+BgorBgEEAdZ5AgQCBIIBbgSCAWoBaAB2 +ABoE/0nQVB1Ar/agw7/x2MRnL07s7iNAaJhrF0Au3Il9AAABkGDSN7EAAAQDAEcw +RQIgVDWwhv7yG6RNnkMZnVq1YYA7ypn/GSH0ibUKnESHRpYCIQCY8gyCX7VFONUI +QuR8daz7ra2FCUI9TwylrR3eFfIgGgB3AN3cyjSV1+EWBeeVMvrHn/g9HFDf2wA6 +FBJ2Ciysu8gqAAABkGDSN5cAAAQDAEgwRgIhAM1edsSyFUKU0Dj1WxTGwziE6fCW +g2ByfL8kDrP260YXAiEA6YQOpJf04N13Nn263BxAl+laH9Ar0eo03fArlv743TQA +dQAN4fIwK9MNwUBiEgnqVS78R3R8sdfpMO8OQh60fk6qNAAAAZBg0je+AAAEAwBG +MEQCIExqK4katETAQo+H0+ImuNJCSeFEI9C+9wrjhl6ZnWb9AiBwkC1vpLYOIm/1 +YCLCQIOmTdg2wf8LITlrQNJA8vbBljANBgkqhkiG9w0BAQsFAAOCAQEASOmPu7ot +yl6MoMns19uI6H2KSUjMFh3/fKMcY/ettmEYalgrytexFMrLnD2UniBlD+nJEshp +5/z7o0YDiRoiLhMAs7VqIdX3erNu/ghNh7P2bDnoMWShSoAKxez1XOGL3rRE0NAi +DsWCaNRHH9rnC97275sbGnua7ZYg+8BiF62vpJlqjrxDHjGiej8qAWSjztbB43Af +bwRscpXTxNkMvOBuRFMH+rSxB8CrOV68W+yxmzPuPxVjM7oJH8Qk5BC53NRqFsVz +JhbNfot0+/drj7JT3jlacUVQcD/BzDuC3+qczQlLjLdHgQM2/e4fXsD6C5S6B11d +BDx6ipGpaASofA== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFojCCA4qgAwIBAgIQU3HI6weE/VEI5dTz4yPsRjANBgkqhkiG9w0BAQsFADBB +MQswCQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxHDAaBgNVBAMME0Fm +ZmlybVRydXN0IFByZW1pdW0wHhcNMTkwMzIxMjA0NjM1WhcNMzAxMjAyMDQwMDAw +WjCBgzELMAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQL +EyJTZWUgd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTEwLwYDVQQDEyhB +ZmZpcm1UcnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVYyMIIBIjANBgkq +hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvDDZHfxkB1nAGFKdw0VCgV+B/eBtW1o+ +bXzwRcpeFh5saDI+tv1RAMrYFq+AJkXCCJopgMF2Wqfv5myE3JMgxEHuuKUpJz7H +FprrFckVOGCtJKH8Iy9AWPjBwt8lKmxGJF7EZst+QoVt4hMe0qhL0WEKbATFPe41 +DcM7UsyQv6Bvpn424uePy3/1ATIsVL3YmvAbUNR0aqVxYAJzTefvyIet/761bKGc +NyqdOVWFFeTDtr8iL1TBXToAgl0GJ39bFQZsP19VcCpfk9Zj3YHTPRPq5wZOZuUN +F7jiBUEi6DaVOi3Wy4vdySHtWPeBHRYif1I6fcUfdCNORMc4ee6KewIDAQABo4IB +UTCCAU0wNwYIKwYBBQUHAQEEKzApMCcGCCsGAQUFBzABhhtodHRwOi8vb2NzcC5h +ZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFHN8mjhoPFF8QQj+oR8qHrRh2808MBIG +A1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgwFoAUncBnpgwi2Sb1RaumZVIRJ9hF +rGMwRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYIKwYBBQUHAgEWJmh0dHBzOi8vd3d3 +LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MEYGA1UdHwQ/MD0wO6A5oDeGNWh0 +dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2NybC9BZmZpcm1UcnVzdFByZW1pdW0u +Y3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUH +AwIwDQYJKoZIhvcNAQELBQADggIBABi64UEwl3l0yIiuSACyVQQIBI60BUmhseac +4BzCAsJrR5tE/2U9QAa2y6JpR1nqm76DJvw1QQgvFcNe+fkwpvoViCaSTbZkGGwD +mQe2xRSYJcDSMQUc/GgzLcX2c1CrexQXE1vwV/q33af1en5s1GzLl915aNS/k1ch +G7EMruJ/D4cuH9j4j2i+b+llmVBzavBwelN5rc693o+Ot9id/1sTWNugwAu3uXGb +VlhETMnjXGIciegOLdWYhWBln0izYlt9IwlDEpjMVaZ0HZlj2JBGaSe4PfEFpJPO +beuPcQpLQGw2XpW2ZMG5JcRYaoKWjixXAGktRA3H9nvVW92jvzx/RX484w2ZM5Rt +E+I1ikAuQLAyWG7clht387e2RuC3NZTtefSyjE3L9gQDOPC+Z9ycwr0WJHRsxFvh +FJQi3JnxgFZf5mc5n2mh3qAgALTNOUHuDiHrerjTOWbpF/1/NJmo/c/YZ63vZIhc +EaER4HuhbBqlpf6z3WOIQdZm1ChwXYHrEcLDgfwm9cXoaVK2HZapkMwQbPffPlT1 +E+AxRFB4YmT1y2WzdaHfhFA9nH6ByUdL5+FfrDoIIUO2e8OLOAcrJsf5+unhAhc0 +v7N48JWdmpstjkXCaCIaidrZLJxS+pikNgHB1dXF/TxokLTiPB9jcYKdGaYs3XHb +YKLdwubu +-----END CERTIFICATE----- diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumeccca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumeccca-chain.pem new file mode 100644 index 00000000000..37b1b787084 --- /dev/null +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/affirmtrustpremiumeccca-chain.pem @@ -0,0 +1,63 @@ +Root Certificate: + Version: 3 (0x2) + Serial Number: 8401224907861490260 (0x7497258ac73f7a54) + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=AffirmTrust, CN=AffirmTrust Premium ECC + Validity + Not Before: Jan 29 14:20:24 2010 GMT + Not After : Dec 31 14:20:24 2040 GMT + +-----BEGIN CERTIFICATE----- +MIIF0zCCBVmgAwIBAgIQFVwk9nYUM5SYOnBd+IoGtzAKBggqhkjOPQQDAzCBhTEL +MAkGA1UEBhMCQ0ExFDASBgNVBAoTC0FmZmlybVRydXN0MSswKQYDVQQLEyJTZWUg +d3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5MTMwMQYDVQQDEypBZmZpcm1U +cnVzdCBFeHRlbmRlZCBWYWxpZGF0aW9uIENBIC0gRVZFQzEwHhcNMjQwNjI4MjE0 +OTUwWhcNMjUwNzI4MjE0OTQ4WjCB2DELMAkGA1UEBhMCQ0ExEDAOBgNVBAgTB09u +dGFyaW8xDzANBgNVBAcTBk90dGF3YTETMBEGCysGAQQBgjc8AgEDEwJDQTEYMBYG +CysGAQQBgjc8AgECEwdPbnRhcmlvMRwwGgYDVQQKExNBZmZpcm10cnVzdCBMaW1p +dGVkMR0wGwYDVQQPExRQcml2YXRlIE9yZ2FuaXphdGlvbjEQMA4GA1UEBRMHMjU0 +MDU0NzEoMCYGA1UEAxMfdmFsaWRwcmVtaXVtZWNjLmFmZmlybXRydXN0LmNvbTB2 +MBAGByqGSM49AgEGBSuBBAAiA2IABEkLBzBYSJPRENKDaA1iBPQz+jZUV+OoM9nJ +sr9sMfmHaqr3nlWxAMM99b9/usVfYyUxqyi+YL2Z3ZSxjX2dpyhwMtPpIQkL1pMW +Iv55XBIcYRyl2NjcADS9B06G+nnix6OCAzcwggMzMAwGA1UdEwEB/wQCMAAwHQYD +VR0OBBYEFP+37ywf2YJJ/4CEVy1GY4ioGm1yMB8GA1UdIwQYMBaAFMaQjAKD113j +vjucLtVlfSoQYO7lMG4GCCsGAQUFBwEBBGIwYDAnBggrBgEFBQcwAYYbaHR0cDov +L29jc3AuYWZmaXJtdHJ1c3QuY29tMDUGCCsGAQUFBzAChilodHRwOi8vYWlhLmFm +ZmlybXRydXN0LmNvbS9hZnRldmVjMWNhLmNydDA+BgNVHR8ENzA1MDOgMaAvhi1o +dHRwOi8vY3JsLmFmZmlybXRydXN0LmNvbS9jcmwvYWZ0ZXZlYzFjYS5jcmwwKgYD +VR0RBCMwIYIfdmFsaWRwcmVtaXVtZWNjLmFmZmlybXRydXN0LmNvbTAOBgNVHQ8B +Af8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMFYGA1UdIARP +ME0wBwYFZ4EMAQEwQgYKKwYBBAGCjwkCBDA0MDIGCCsGAQUFBwIBFiZodHRwczov +L3d3dy5hZmZpcm10cnVzdC5jb20vcmVwb3NpdG9yeTCCAX4GCisGAQQB1nkCBAIE +ggFuBIIBagFoAHUA5tIxY0B3jMEQQQbXcbnOwdJA9paEhvu6hzId/R43jlAAAAGQ +YNN5tQAABAMARjBEAiAnainEoBGI9czVh+c9QLPL30S3Rtov8zrnhlXfeKLzZQIg +UGkntBMux0MqHt9Aj60qMsS/C4ZWF7AihVVaUKcrEVgAdgAN4fIwK9MNwUBiEgnq +VS78R3R8sdfpMO8OQh60fk6qNAAAAZBg03m1AAAEAwBHMEUCIGI9kBByoozH4cfS +ECW/O2N/ElkdATkt7EwQ52kcc4ICAiEA9QTh8JlJTb/ytYC1ECX0vQbrYVexg+fu +dw7dfToF9nAAdwAS8U40vVNyTIQGGcOPP3oT+Oe1YoeInG0wBYTr5YYmOgAAAZBg +03ndAAAEAwBIMEYCIQCox5nSCcVB2AfNYXco77zsJnYP7KAU2I4VA2GNL7I4wQIh +AP6WEzyfBoGpYYqFmNnJUavyhKBmeNiR7eNtaFwpSc+UMAoGCCqGSM49BAMDA2gA +MGUCMAGSNMXAAKDRk0ZOtydN95Rkja97+70TatCIIxEAsJD8Hu7lfj2LHCYFQjVY +oaWTrQIxAKUudx7E/JnjsthuL6sNqKVHfD3iLUJyQNK9wE0SVt1xAm7Cu1JXZORE +M64KMKoQFQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDXDCCAuKgAwIBAgIQAgKlhME0Bk3J8y0gfqNymDAKBggqhkjOPQQDAzBFMQsw +CQYDVQQGEwJVUzEUMBIGA1UECgwLQWZmaXJtVHJ1c3QxIDAeBgNVBAMMF0FmZmly +bVRydXN0IFByZW1pdW0gRUNDMB4XDTE5MDMyMTIwNTUwN1oXDTMwMTIwMjA0MDAw +MFowgYUxCzAJBgNVBAYTAkNBMRQwEgYDVQQKEwtBZmZpcm1UcnVzdDErMCkGA1UE +CxMiU2VlIHd3dy5hZmZpcm10cnVzdC5jb20vcmVwb3NpdG9yeTEzMDEGA1UEAxMq +QWZmaXJtVHJ1c3QgRXh0ZW5kZWQgVmFsaWRhdGlvbiBDQSAtIEVWRUMxMHYwEAYH +KoZIzj0CAQYFK4EEACIDYgAEu9f5NkumdaVlmaNaxpDB+rBk/S6lhqcUU1zTLcRz +4G0dr4290hezjrvZJxGJ/X15aexpdD2V9cwaPD/yuEJcaaz+rg/qDoqQF3+AFqVc +41jw1E0S59+57XVKLtXI7Xh6o4IBVDCCAVAwNwYIKwYBBQUHAQEEKzApMCcGCCsG +AQUFBzABhhtodHRwOi8vb2NzcC5hZmZpcm10cnVzdC5jb20wHQYDVR0OBBYEFMaQ +jAKD113jvjucLtVlfSoQYO7lMBIGA1UdEwEB/wQIMAYBAf8CAQAwHwYDVR0jBBgw +FoAUmq8pesARNTUmUTAAw2r+QNWu1jwwRwYDVR0gBEAwPjA8BgRVHSAAMDQwMgYI +KwYBBQUHAgEWJmh0dHBzOi8vd3d3LmFmZmlybXRydXN0LmNvbS9yZXBvc2l0b3J5 +MEkGA1UdHwRCMEAwPqA8oDqGOGh0dHA6Ly9jcmwuYWZmaXJtdHJ1c3QuY29tL2Ny +bC9BZmZpcm1UcnVzdFByZW1pdW1FQ0MuY3JsMA4GA1UdDwEB/wQEAwIBhjAdBgNV +HSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwCgYIKoZIzj0EAwMDaAAwZQIwHJ5g +a6sHvQ51DGr0bWq34awuwlWbybC2grHoNp5uYapcXr/qTJusb/6n+dczqFdaAjEA +7VQY06fE9ifMnTgT9824jc3+H6kfhMk4PoIj9ouWdYfc1DyTBS/low9Hb8liQyFr +-----END CERTIFICATE----- diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrust2048ca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrust2048ca-chain.pem new file mode 100644 index 00000000000..253072d00ed --- /dev/null +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrust2048ca-chain.pem @@ -0,0 +1,76 @@ +Root Certificate: + Version: 3 (0x2) + Serial Number: 946069240 (0x3863def8) + Signature Algorithm: sha1WithRSAEncryption + Issuer: O=Entrust.net, OU=www.entrust.net/CPS_2048 incorp. by ref. (limits liab.), OU=(c) 1999 Entrust.net Limited, CN=Entrust.net Certification Authority (2048) + Validity + Not Before: Dec 24 17:50:51 1999 GMT + Not After : Jul 24 14:15:12 2029 GMT + +-----BEGIN CERTIFICATE----- +MIIGiDCCBXCgAwIBAgIQS5P8oVcgTBT74PnIwDQivjANBgkqhkiG9w0BAQsFADCB +ujELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsT +H1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAy +MDEyIEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEuMCwG +A1UEAxMlRW50cnVzdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEwxSzAeFw0y +MzEwMDIxOTE4MTBaFw0yNDExMDIxOTE4MDlaMGkxCzAJBgNVBAYTAkNBMRAwDgYD +VQQIEwdPbnRhcmlvMQ8wDQYDVQQHEwZPdHRhd2ExGDAWBgNVBAoTD0VudHJ1c3Qg +TGltaXRlZDEdMBsGA1UEAxMUMjA0OHRlc3QuZW50cnVzdC5uZXQwggEiMA0GCSqG +SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCgkrsKoDEHyJjll/fu7mjvtbookb50rzTI +i+jQzvtL8AJOcCfxJL1cVriufc/zRYdSQeRJxkbUb+SqIJkec+27onPpY3xOjJAK +bWdmac1Iv9JPXYMpKJXnOGrooeXEtCcKSKphx4VhHnLA67BGfSNfHLm4JwghX4jY +VpZ8P89gmh8l1eLRP+b3y7OzEkFliwmErALSD8i/bkzE+GxYMnpg/HI2Iw1lakxE +wZOg0ydgl7jHWZUDdnxhAvLS/hfzPVhi9ZwgoXQJiUXUp0JJo6QgVOIC5IztpdZa +3HW1VK7a0eTLhmdFRx39ARn/GbbIyoIqUzLOhAa2cbsGIJjtXjhrAgMBAAGjggLY +MIIC1DAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRHn0CebGnHRqTZTeTYCbPHhiVB +MzAfBgNVHSMEGDAWgBSConB03bxTP8971PfNf6dgxgpMvzBoBggrBgEFBQcBAQRc +MFowIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmVudHJ1c3QubmV0MDMGCCsGAQUF +BzAChidodHRwOi8vYWlhLmVudHJ1c3QubmV0L2wxay1jaGFpbjI1Ni5jZXIwMwYD +VR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9sZXZlbDFrLmNy +bDAfBgNVHREEGDAWghQyMDQ4dGVzdC5lbnRydXN0Lm5ldDAOBgNVHQ8BAf8EBAMC +BaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBMGA1UdIAQMMAowCAYG +Z4EMAQICMIIBfgYKKwYBBAHWeQIEAgSCAW4EggFqAWgAdwA/F0tP1yJHWJQdZRyE +vg0S7ZA3fx+FauvBvyiF7PhkbgAAAYrx05lbAAAEAwBIMEYCIQDbMXKdzSr90jM+ +TekjpqVTEBDDvub7+AEx/kQYzf9gugIhAKPCjJmIh1NZrKkwK8MsOEL4jkN6FJ/h +4kiiJoze3fB/AHYAdv+IPwq2+5VRwmHM9Ye6NLSkzbsp3GhCCp/mZ0xaOnQAAAGK +8dOZVAAABAMARzBFAiAW11p7sV2byjrpk6AMQrMGwV2CuT3AKNuQVyxva7XQPAIh +AP1P7DfYsZ1aR12Tkg2x2BYjFrlsJCl36n5I/565xQk4AHUA2ra/az+1tiKfm8K7 +XGvocJFxbLtRhIU0vaQ9MEjX+6sAAAGK8dOZnwAABAMARjBEAiA43NURCcnHNpkH +XggwpVY9QYNIEAjpHEcPmyXJuQ9y8QIgPqx0MnlKXLuJVReuI5Hzc3iFtcYo070d +UYWH2AuVaFwwDQYJKoZIhvcNAQELBQADggEBAIZoSHApNF6DNYvGKHZJX411QkA0 +5zkq3dcm95BFomaqroEp1QeUeQ8e6xofUs84CURzopE9P81JBHX2Qzb/VeBzZOKy +dekaoz4NGW5ZvpMh7HXXaUpHKU/xZ5uUHVSatBU+cnidPhgn1czntqOwjzsgEZNW +/wbPEjqvIrZvAW4DPak/MSwlENys4ty5gX4453S5gwd18b+NFBq44O/FofR8bvWU +3lJ3VcVeONDzTcXPv+Yd1SlyO1/eXdWlFqloYFjkpcQ4wSLbOEeiWWITkZ0xCAxQ +j8uWuDOSyFQLpaPJvEuG1dlho7RZdor0flUIxYfqg2Nr4Svq1ezskwrdQm0= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFKjCCBBKgAwIBAgIQLgRRzl0kJMcrXWV2cWUG2DANBgkqhkiG9w0BAQsFADCB +tDEUMBIGA1UEChMLRW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5l +dC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNV +BAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1 +c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw0yMjExMjUy +MTE5NDNaFw0yOTA3MjMwMDAwMDBaMIG6MQswCQYDVQQGEwJVUzEWMBQGA1UEChMN +RW50cnVzdCwgSW5jLjEoMCYGA1UECxMfU2VlIHd3dy5lbnRydXN0Lm5ldC9sZWdh +bC10ZXJtczE5MDcGA1UECxMwKGMpIDIwMTIgRW50cnVzdCwgSW5jLiAtIGZvciBh +dXRob3JpemVkIHVzZSBvbmx5MS4wLAYDVQQDEyVFbnRydXN0IENlcnRpZmljYXRp +b24gQXV0aG9yaXR5IC0gTDFLMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC +AQEA2j+W0E25L0Tn2zlem1DuXKVh2kFnUwmqAJqOV38pa9vH4SEkqjrQjUcj0u1y +FvCRIdJdt7hLqIOPt5EyaM/OJZMssn2XyP7BtBe6CZ4DkJN7fEmDImiKm95HwzGY +ei59QAvS7z7Tsoyqj0ip/wDoKVgG97aTWpRzJiatWA7lQrjV6nN5ZGhTJbiEz5R6 +rgZFDKNrTdDGvuoYpDbwkrK6HIiPOlJ/915tgxyd8B/lw9bdpXiSPbBtLOrJz5RB +GXFEaLpHPATpXbo+8DX3Fbae8i4VHj9HyMg4p3NFXU2wO7GOFyk36t0FASK7lDYq +jVs1/lMZLwhGwSqzGmIdTivZGwIDAQABo4IBLjCCASowEgYDVR0TAQH/BAgwBgEB +/wIBADAdBgNVHQ4EFgQUgqJwdN28Uz/Pe9T3zX+nYMYKTL8wHwYDVR0jBBgwFoAU +VeSB0RGAvtiJuQijMfmhJAkWuXAwMwYIKwYBBQUHAQEEJzAlMCMGCCsGAQUFBzAB +hhdodHRwOi8vb2NzcC5lbnRydXN0Lm5ldDAyBgNVHR8EKzApMCegJaAjhiFodHRw +Oi8vY3JsLmVudHJ1c3QubmV0LzIwNDhjYS5jcmwwDgYDVR0PAQH/BAQDAgEGMB0G +A1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjA8BgNVHSAENTAzMDEGBFUdIAAw +KTAnBggrBgEFBQcCARYbaHR0cHM6Ly93d3cuZW50cnVzdC5uZXQvcnBhMA0GCSqG +SIb3DQEBCwUAA4IBAQAuAlHLO8CoKt2a4I23UDkKc7kQI3nUkWqq2RxRh8a/4TEF +C9WSF03EHVBW9JZZcrZ3ZdTDRsNF8vSqmCABz1FLu6vw3D3bEXELonAYlkmeFFV7 +1hiW9AdyMJD92XsXiU0Yr9J76Tk4iknMTTHiZXdZOcPMOXlMwPy++HS5tTIyqO0d +zl1PS8tlCcZrKaNNKbmiIWPhmBUSog9IQt2VKpoAIP8tlvRt5tHf5qW5m7vp7qmG +HF2ou54+qQIXO6jIP8CQ4xWvj0aiLklTNMkvXesaVq0xzNgRkx9ZzhREfbuM6eWc +GQHwG7m+JmfL+u1dCAZhh4Uyn5oLU9gogFM6v4jX +-----END CERTIFICATE----- diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustevca-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustevca-chain.pem new file mode 100644 index 00000000000..e9c06b19c69 --- /dev/null +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustevca-chain.pem @@ -0,0 +1,79 @@ +Root Certificate: + Version: 3 (0x2) + Serial Number: 1164660820 (0x456b5054) + Signature Algorithm: sha1WithRSAEncryption + Issuer: C=US, O=Entrust, Inc., OU=www.entrust.net/CPS is incorporated by reference, OU=(c) 2006 Entrust, Inc., CN=Entrust Root Certification Authority + Validity + Not Before: Nov 27 20:23:42 2006 GMT + Not After : Nov 27 20:53:42 2026 GMT + +-----BEGIN CERTIFICATE----- +MIIHEjCCBfqgAwIBAgIQFhH4VGskTR+tQK3JbN63kTANBgkqhkiG9w0BAQsFADCB +sTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsT +MHd3dy5lbnRydXN0Lm5ldC9ycGEgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5j +ZTEfMB0GA1UECxMWKGMpIDIwMDkgRW50cnVzdCwgSW5jLjEuMCwGA1UEAxMlRW50 +cnVzdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEwxRTAeFw0yNDA2MjgyMTQw +NDVaFw0yNTA3MjgyMTQwNDRaMIHIMQswCQYDVQQGEwJDQTEQMA4GA1UECBMHT250 +YXJpbzEPMA0GA1UEBxMGT3R0YXdhMRMwEQYLKwYBBAGCNzwCAQMTAkNBMRgwFgYL +KwYBBAGCNzwCAQITB09udGFyaW8xGDAWBgNVBAoTD0VudHJ1c3QgTGltaXRlZDEd +MBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEDAOBgNVBAUTBzE5MTM2MDUx +HDAaBgNVBAMTE3ZhbGlkZXYuZW50cnVzdC5uZXQwggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDL2vkrBEZ5qeVdac1C01bcNnoeCU3AVU3Fh1Ifldic9/Gw +xqNVOFYQNzTk8M62FnPUvas4MnXmeBkPhhym+dnjsM22EeS2p6gTlvOGtJFVr+Ix +vq1UAKtqK0gYGriW6SexroSYiG1O0aeqEnKSLlEBHYhmacj2jlbx0ToxMfdBMRRq +4UjnIrh/CBochxt7aKv525tChnZGMT06QKAjx71w2cou0C05v83KJ75EI4EAmTfE +z9sKJeST5pH5MI3WKcP6ZmXynKYSIpIGb4Z8B9Ftp8HdzdR9EafOSlRlbIkEn3lm +nq4UCph48/PsUcJoViBCoY6zDLcPGt3gGQVIjq3vAgMBAAGjggMLMIIDBzAMBgNV +HRMBAf8EAjAAMB0GA1UdDgQWBBRF6MZkqXf3sICXuvbrBH1R9I8bAjAfBgNVHSME +GDAWgBRbQYqyxEPBvb/IVEFVneCWrf+5oTBlBggrBgEFBQcBAQRZMFcwIwYIKwYB +BQUHMAGGF2h0dHA6Ly9vY3NwLmVudHJ1c3QubmV0MDAGCCsGAQUFBzAChiRodHRw +Oi8vYWlhLmVudHJ1c3QubmV0L2wxZS1jaGFpbi5jZXIwMwYDVR0fBCwwKjAooCag +JIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9sZXZlbDFlLmNybDAeBgNVHREEFzAV +ghN2YWxpZGV2LmVudHJ1c3QubmV0MA4GA1UdDwEB/wQEAwIFoDAdBgNVHSUEFjAU +BggrBgEFBQcDAQYIKwYBBQUHAwIwSwYDVR0gBEQwQjAHBgVngQwBATA3BgpghkgB +hvpsCgECMCkwJwYIKwYBBQUHAgEWG2h0dHBzOi8vd3d3LmVudHJ1c3QubmV0L3Jw +YTCCAX0GCisGAQQB1nkCBAIEggFtBIIBaQFnAHUAEvFONL1TckyEBhnDjz96E/jn +tWKHiJxtMAWE6+WGJjoAAAGQYMsp8gAABAMARjBEAiAL794Fw7wyzricvRl+2AON +FbGf2hwDB3wh8RkGLBRQ7AIgTCarii0atho7ZeUO3h66Ug7s7WxnF9onDZrtoMrH +U9MAdQAN4fIwK9MNwUBiEgnqVS78R3R8sdfpMO8OQh60fk6qNAAAAZBgyyoMAAAE +AwBGMEQCIFaXc4M9C9mNukrV68Sc2E5lw9srQ80nMBCGseY99nFxAiAppQmR9FKC +TE/ROlgZRfimx61W4k+SaQ52eek4JNWXXwB3ABoE/0nQVB1Ar/agw7/x2MRnL07s +7iNAaJhrF0Au3Il9AAABkGDLKi0AAAQDAEgwRgIhAPFUevU47H5uJqYL5y1ClFS7 +mEve7E8350JKnR1VykGLAiEArn7VAJcmRNNCDAegsHCCLlpasz9PLHFd9XHQAwvL +IFwwDQYJKoZIhvcNAQELBQADggEBAHfMCQP5Y+7IYzqOh5D/81WqHagmWOqkJYsN +33uux44fhVGqiG1O5ImTQsxJpt/HmDuK1qLEjG31Y9q89U91KAqLQauCQ5iMXrBg +TlwK8kzO1XYC5KkpO5ZWanqfjOahM9mkEKHPV9srwj6xTbInCq9DabRwuWyohj3b +EKrmB016TOT0hJ94jCb8PWl15oQJdsGlEfrG7amtDSRuoDHVA3nXJIJqx5LVnErB +glfsAmP8TPkWYY8kuNE2Rjr2M6P5LRLEvtRELCQF3lPuY0+xxGksGVM207YqhYKv +GzMmA8c7tF3ZclbE0rUA2T8FuBuweAV8tnWq2TaeAHWIJ4nY17s= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFHjCCBAagAwIBAgIRAIZmsCrBy1RAAAAAAFHTWJwwDQYJKoZIhvcNAQELBQAw +gbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkwNwYDVQQL +EzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu +Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVu +dHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0xOTA2MTkxNjUy +MDhaFw0yNjExMTkxNzIyMDhaMIGxMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNRW50 +cnVzdCwgSW5jLjE5MDcGA1UECxMwd3d3LmVudHJ1c3QubmV0L3JwYSBpcyBpbmNv +cnBvcmF0ZWQgYnkgcmVmZXJlbmNlMR8wHQYDVQQLExYoYykgMjAwOSBFbnRydXN0 +LCBJbmMuMS4wLAYDVQQDEyVFbnRydXN0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5 +IC0gTDFFMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtlsEVHfdDiRm +3Cqh24DMXcdf/VIWWNpflAapuLa5YwxHIILsx5VOi7h3Umo9tYep1uHMdOWmyMDU +Vk+NLtYIPgxMQz7wQZNeRu8559llKgx2UCe9Ww0zMwfg96KpnOERM61m/NIseqqj +cxa+k4V1D9c3jPojt2T440xu7bMFveI223zedkTagnJ2tm7/lKHQhvcQzUpai7B1 +jGZSgE5ITEmDpkDXd4ETTV5yfkhGIqoP4j5llDjhcnH+SnEJujV/VYk9gdW4KAEQ +dzZaEIXSvWCEK0lhlAzeTEBqKsR5YIQkgjJpSphL4lYQugNFUSDTz9qOVBtFtnq6 +l5pa2MbRXwIDAQABo4IBLjCCASowDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQG +CCsGAQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMDMGCCsGAQUF +BwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMwYD +VR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9yb290Y2ExLmNy +bDA7BgNVHSAENDAyMDAGBFUdIAAwKDAmBggrBgEFBQcCARYaaHR0cDovL3d3dy5l +bnRydXN0Lm5ldC9ycGEwHQYDVR0OBBYEFFtBirLEQ8G9v8hUQVWd4Jat/7mhMB8G +A1UdIwQYMBaAFGiQ5GekplOAx4ZmpPH3S0P7hL1tMA0GCSqGSIb3DQEBCwUAA4IB +AQAPUNBX97sqIXZl/zLu53iv7a0HK7prvD0cVaZM0yRfVptvARgjIZZzTtv32v6X +wSr4fDeRmpLaTWtipBGSqh3fNkTSVT8GGBq6+h1lrPEYv6jnStDf7VLQxVliKt2w +h34JjgRUx9rdia30tk/EpPavkxxPks8vjoLN3f4dbkIY/sfljyZbseqVLx9kl/we +OvqL6jZgaQOapFQLZJze7VwLiPVuUnW8ddK3JIE1a5YCZs0irIW5+96ttznIgPK2 +aUOmHQp/zasi7SFl49HrKGKWtZuyDB9U56e01H6PDTpSSSTPyLsSVg3JALHBPDzS +bBraAU3wuAyc3BQ4OIOmwwnT +-----END CERTIFICATE----- diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcaec1-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcaec1-chain.pem new file mode 100644 index 00000000000..8ea22c05b80 --- /dev/null +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcaec1-chain.pem @@ -0,0 +1,66 @@ +Root Certificate: + Version: 3 (0x2) + Serial Number: + a6:8b:79:29:00:00:00:00:50:d0:91:f9 + Signature Algorithm: ecdsa-with-SHA384 + Issuer: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2012 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - EC1 + Validity + Not Before: Dec 18 15:25:36 2012 GMT + Not After : Dec 18 15:55:36 2037 GMT + +-----BEGIN CERTIFICATE----- +MIIFzDCCBVOgAwIBAgIQcbNJ8XJLeT3fV8DU3QNYSDAKBggqhkjOPQQDAzCBujEL +MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1Nl +ZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDE2 +IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEuMCwGA1UE +AxMlRW50cnVzdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEwxSjAeFw0yNDA2 +MjgyMTM5MzVaFw0yNTA3MjgyMTM5MzRaMIHLMQswCQYDVQQGEwJDQTEQMA4GA1UE +CBMHT250YXJpbzEPMA0GA1UEBxMGT3R0YXdhMRMwEQYLKwYBBAGCNzwCAQMTAkNB +MRgwFgYLKwYBBAGCNzwCAQITB09udGFyaW8xGDAWBgNVBAoTD0VudHJ1c3QgTGlt +aXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgNVBAUTCjEw +MDA0OTI4NzkxHDAaBgNVBAMTE3ZhbGlkZWMuZW50cnVzdC5uZXQwdjAQBgcqhkjO +PQIBBgUrgQQAIgNiAAS90ZyZ86Gl5Fh1qJ/70UwyQWATu3igiQLeVVvZ4G79SBEG +Xc4TcAn0LzBhfJonAzWFkAS860ARjvFHgUj0otyT+Q2/zC9c8CjOsL3bYp3SNUbC +FWBhIV0vhGGY8NafeXCjggMJMIIDBTAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBTP +DXJE/iZfi5wUSAo4GN4thBCCHDAfBgNVHSMEGDAWgBTD+UUDvsj5CzxFNfPrcuzn +6OuUmzBjBggrBgEFBQcBAQRXMFUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmVu +dHJ1c3QubmV0MC4GCCsGAQUFBzAChiJodHRwOi8vYWlhLmVudHJ1c3QubmV0L2wx +ai1lYzEuY2VyMDMGA1UdHwQsMCowKKAmoCSGImh0dHA6Ly9jcmwuZW50cnVzdC5u +ZXQvbGV2ZWwxai5jcmwwHgYDVR0RBBcwFYITdmFsaWRlYy5lbnRydXN0Lm5ldDAO +BgNVHQ8BAf8EBAMCB4AwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMEsG +A1UdIAREMEIwBwYFZ4EMAQEwNwYKYIZIAYb6bAoBAjApMCcGCCsGAQUFBwIBFhto +dHRwczovL3d3dy5lbnRydXN0Lm5ldC9ycGEwggF9BgorBgEEAdZ5AgQCBIIBbQSC +AWkBZwB1AA3h8jAr0w3BQGISCepVLvxHdHyx1+kw7w5CHrR+Tqo0AAABkGDKGokA +AAQDAEYwRAIgZwtzml8YzKjqeP86zX+88q8sHOt//2Qmahr2tk97ozUCIFCOM2nF +s1GJVBjKQZEH8QqkivVp+Cai9pC/57TiOmCOAHUAzPsPaoVxCWX+lZtTzumyfCLp +hVwNl422qX5UwP5MDbAAAAGQYMoamAAABAMARjBEAiEA37X8EgQAUzLxn/Ny1Yx3 +uszQF5D85m8vZ0otf8nHzuwCH168zpAxzKS71Fz6CgmDS0QZOfBSYFBD+Pdcm6e1 +ilkAdwAS8U40vVNyTIQGGcOPP3oT+Oe1YoeInG0wBYTr5YYmOgAAAZBgyhq6AAAE +AwBIMEYCIQCljVuYzRe6oQTZPdx0tGhIQSOwM1JbxoMJu2cW+gEGLAIhAMSSJoni +0KT3KavwtsSWuuHsWjt8atv6TpJtLmVxCIdlMAoGCCqGSM49BAMDA2cAMGQCMBPY +1dn1Js8F9b08aVCZ3vqDGFTKuzTXaxArf/y/WhLtcHdZPLaYVifQcAKzp1WCFQIw +MvpE6RDccmnZi5TX88p16s8ev/qkegpbf7Xuw1JQEfy2NRwrXc+NwA422EjXBTti +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIID5zCCA2ygAwIBAgIQCoPUgD5+n1EAAAAAUdTB9zAKBggqhkjOPQQDAzCBvzEL +MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsTH1Nl +ZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAyMDEy +IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEzMDEGA1UE +AxMqRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRUMxMB4X +DTE2MDQwNTIwMTk1NFoXDTM3MTAwNTIwNDk1NFowgboxCzAJBgNVBAYTAlVTMRYw +FAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1c3Qu +bmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNiBFbnRydXN0LCBJbmMu +IC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxLjAsBgNVBAMTJUVudHJ1c3QgQ2Vy +dGlmaWNhdGlvbiBBdXRob3JpdHkgLSBMMUowdjAQBgcqhkjOPQIBBgUrgQQAIgNi +AAT14eFXmpQX/dEf7NAxrMH13n0btz1KKvH2S1rROGPAKex2CY8yxznbffK/MbCk +F7ByYXGs1+8kL5xmTysU/c+YmjOZx2mMSAk2DPw30fijJ3tRrwChZ+TBpgtB6+A5 +MsCjggEuMIIBKjAOBgNVHQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAz +BggrBgEFBQcBAQQnMCUwIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmVudHJ1c3Qu +bmV0MDMGA1UdHwQsMCowKKAmoCSGImh0dHA6Ly9jcmwuZW50cnVzdC5uZXQvZWMx +cm9vdC5jcmwwOwYDVR0gBDQwMjAwBgRVHSAAMCgwJgYIKwYBBQUHAgEWGmh0dHA6 +Ly93d3cuZW50cnVzdC5uZXQvcnBhMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEF +BQcDAjAdBgNVHQ4EFgQUw/lFA77I+Qs8RTXz63Ls5+jrlJswHwYDVR0jBBgwFoAU +t2PnGt2N6QimVYOk4GpQQWURQkkwCgYIKoZIzj0EAwMDaQAwZgIxAPnVAOqxKDd7 +v37EBmpPqWCCWBFPKW6HpRx3GUWc9caeQIw8rO2HXYgf92pb/TsJYAIxAJhI0MpR +z5L42xF1R9UIPfQxCMwgsnWBqIqcfMrMO+2DxQy6GIP3cFFj9gRyxguKWw== +-----END CERTIFICATE----- diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcag2-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcag2-chain.pem new file mode 100644 index 00000000000..5fcbf9ffc2c --- /dev/null +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcag2-chain.pem @@ -0,0 +1,80 @@ +Root Certificate: + Version: 3 (0x2) + Serial Number: 1246989352 (0x4a538c28) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2009 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - G2 + Validity + Not Before: Jul 7 17:25:54 2009 GMT + Not After : Dec 7 17:55:54 2030 GMT + +-----BEGIN CERTIFICATE----- +MIIHOzCCBiOgAwIBAgIQWFfRPoYcAxEc+S0tOlD+ljANBgkqhkiG9w0BAQsFADCB +ujELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsT +H1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAy +MDE0IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEuMCwG +A1UEAxMlRW50cnVzdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEwxTTAeFw0y +NDA2MjgyMTQyMTRaFw0yNTA3MjgyMTQyMTNaMIHLMQswCQYDVQQGEwJDQTEQMA4G +A1UECBMHT250YXJpbzEPMA0GA1UEBxMGT3R0YXdhMRMwEQYLKwYBBAGCNzwCAQMT +AkNBMRgwFgYLKwYBBAGCNzwCAQITB09udGFyaW8xGDAWBgNVBAoTD0VudHJ1c3Qg +TGltaXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgNVBAUT +CjEwMDA0OTI4NzkxHDAaBgNVBAMTE3ZhbGlkZzIuZW50cnVzdC5uZXQwggEiMA0G +CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCZ66eWZS5ytmbHJeHcA9WfnpbGFC04 +Tov7L0NWiStVRPEFrXrGSn6RPriGci6RwrCz5yn47EWjk2AjSD4e5lySDKHwTg+0 +S9pl3lcSd8tQOTbTwVM0EfOxdUlO4IY0jCOSM8rnZUc1JvEIIrXWXWF9AWoDb4BQ +erTefRm/YykFC558PEzn84vU9KoEmDwIP4upWKVutuzBpHWhZW3q9wagg62KifHN +1yaagv4PUGgdkrVkyA1ZO3D7b2RpQjBreOTk+tsTnWtbAkFGtRBOA/2QrEvyqMU7 +eCnpFZMIaj2tKeSLqhIWxzOnrAGUJNp5wLYmVnnhPhHEv1g79pNsZLR3AgMBAAGj +ggMoMIIDJDAMBgNVHRMBAf8EAjAAMB0GA1UdDgQWBBRt85gfkWUjfTKgrLytMp8o +VvOe3zAfBgNVHSMEGDAWgBTD99C1KjCtrw2RIXA5VN28iXDHOjBoBggrBgEFBQcB +AQRcMFowIwYIKwYBBQUHMAGGF2h0dHA6Ly9vY3NwLmVudHJ1c3QubmV0MDMGCCsG +AQUFBzAChidodHRwOi8vYWlhLmVudHJ1c3QubmV0L2wxbS1jaGFpbjI1Ni5jZXIw +MwYDVR0fBCwwKjAooCagJIYiaHR0cDovL2NybC5lbnRydXN0Lm5ldC9sZXZlbDFt +LmNybDA3BgNVHREEMDAughN2YWxpZGcyLmVudHJ1c3QubmV0ghd3d3cudmFsaWRn +Mi5lbnRydXN0Lm5ldDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUH +AwEGCCsGAQUFBwMCMEsGA1UdIAREMEIwBwYFZ4EMAQEwNwYKYIZIAYb6bAoBAjAp +MCcGCCsGAQUFBwIBFhtodHRwczovL3d3dy5lbnRydXN0Lm5ldC9ycGEwggF+Bgor +BgEEAdZ5AgQCBIIBbgSCAWoBaAB3ABLxTjS9U3JMhAYZw48/ehP457Vih4icbTAF +hOvlhiY6AAABkGDMhQQAAAQDAEgwRgIhAMzddgbnWlodtosz6EMh2Y89n0JR4eMO +v+W6tUp2gVwYAiEA6UKa2eFlX0KdzuZCvTlPgi8DeK3ZI2wffyV2bYMXtsIAdgAN +4fIwK9MNwUBiEgnqVS78R3R8sdfpMO8OQh60fk6qNAAAAZBgzIURAAAEAwBHMEUC +IQDmVH2NlaV2/Y3OaPMXhH+BT63zA+Bh/5aCfPiYrJ7K2AIgRADPHzpwS7bfvVZI +k8QxUBSCDXFmZQOrpamBaEko6YIAdQDM+w9qhXEJZf6Vm1PO6bJ8IumFXA2Xjbap +flTA/kwNsAAAAZBgzIUGAAAEAwBGMEQCIA1CHfNw7cCcJSb3s7ik9Wflf3irqE9G +QKxZ+Y9BOIx0AiA6CMvw7OHjG519E1tZgr/HFRXzxKchBp80dfsaEKxY9zANBgkq +hkiG9w0BAQsFAAOCAQEAqvn1CTObiV5zKVY6NWjGK49Wqsr9t1ok/h/yfKRmr36O +UZkMTPANj0uhwM4gtieTze9hnNzEkx1ec6G40JyABRiSX+0dtq3n8wiW3d8G1Qj5 +/s8yZ13/ATrdjjr1mlGOvh0sgWTTPaQpl8ijXTy40GYpZIUXXBK09Rm6W0siq+7m +OHNpJR4APWOBBU4QwiWrHHsFq4KvwxiTjNWWizCOnZwVi3awNBoDD/Iwszn+trOA +8U/1SsHGuPBWKajcGorwi2zQ99JxAwJJ8XNBCekynjbPZYx52KkqfR07Fd2Occbl +3lh3wXrepzzU1a6vdyiQpagX8btyIqQpAzytypzaLQ== +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIFLTCCBBWgAwIBAgIMYaHn0gAAAABR02amMA0GCSqGSIb3DQEBCwUAMIG+MQsw +CQYDVQQGEwJVUzEWMBQGA1UEChMNRW50cnVzdCwgSW5jLjEoMCYGA1UECxMfU2Vl +IHd3dy5lbnRydXN0Lm5ldC9sZWdhbC10ZXJtczE5MDcGA1UECxMwKGMpIDIwMDkg +RW50cnVzdCwgSW5jLiAtIGZvciBhdXRob3JpemVkIHVzZSBvbmx5MTIwMAYDVQQD +EylFbnRydXN0IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjAeFw0x +NDEyMTUxNTI1MDNaFw0zMDEwMTUxNTU1MDNaMIG6MQswCQYDVQQGEwJVUzEWMBQG +A1UEChMNRW50cnVzdCwgSW5jLjEoMCYGA1UECxMfU2VlIHd3dy5lbnRydXN0Lm5l +dC9sZWdhbC10ZXJtczE5MDcGA1UECxMwKGMpIDIwMTQgRW50cnVzdCwgSW5jLiAt +IGZvciBhdXRob3JpemVkIHVzZSBvbmx5MS4wLAYDVQQDEyVFbnRydXN0IENlcnRp +ZmljYXRpb24gQXV0aG9yaXR5IC0gTDFNMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A +MIIBCgKCAQEA0IHBOSPCsdHs91fdVSQ2kSAiSPf8ylIKsKs/M7WwhAf23056sPuY +Ij0BrFb7cW2y7rmgD1J3q5iTvjOK64dex6qwymmPQwhqPyK/MzlG1ZTy4kwFItln +gJHxBEoOm3yiydJs/TwJhL39axSagR3nioPvYRZ1R5gTOw2QFpi/iuInMlOZmcP7 +lhw192LtjL1JcdJDQ6Gh4yEqI3CodT2ybEYGYW8YZ+QpfrI8wcVfCR5uRE7sIZlY +FUj0VUgqtzS0BeN8SYwAWN46lsw53GEzVc4qLj/RmWLoquY0djGqr3kplnjLgRSv +adr7BLlZg0SqCU+01CwBnZuUMWstoc/B5QIDAQABo4IBKzCCAScwDgYDVR0PAQH/ +BAQDAgEGMB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8E +CDAGAQH/AgEAMDMGCCsGAQUFBwEBBCcwJTAjBggrBgEFBQcwAYYXaHR0cDovL29j +c3AuZW50cnVzdC5uZXQwMAYDVR0fBCkwJzAloCOgIYYfaHR0cDovL2NybC5lbnRy +dXN0Lm5ldC9nMmNhLmNybDA7BgNVHSAENDAyMDAGBFUdIAAwKDAmBggrBgEFBQcC +ARYaaHR0cDovL3d3dy5lbnRydXN0Lm5ldC9ycGEwHQYDVR0OBBYEFMP30LUqMK2v +DZEhcDlU3byJcMc6MB8GA1UdIwQYMBaAFGpyJnrQHu995ztpUdRsjZ+QEmarMA0G +CSqGSIb3DQEBCwUAA4IBAQC0h8eEIhopwKR47PVPG7SEl2937tTPWa+oQ5YvHVje +pvMVWy7ZQ5xMQrkXFxGttLFBx2YMIoYFp7Qi+8VoaIqIMthx1hGOjlJ+Qgld2dnA +DizvRGsf2yS89byxqsGK5Wbb0CTz34mmi/5e0FC6m3UAyQhKS3Q/WFOv9rihbISY +Jnz8/DVRZZgeO2x28JkPxLkJ1YXYJKd/KsLak0tkuHB8VCnTglTVz6WUwzOeTTRn +4Dh2ZgCN0C/GqwmqcvrOLzWJ/MDtBgO334wlV/H77yiI2YIowAQPlIFpI+CRKMVe +1QzX1CA778n4wI+nQc1XRG5sZ2L+hN/nYNjvv9QiHg3n +-----END CERTIFICATE----- diff --git a/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcag4-chain.pem b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcag4-chain.pem new file mode 100644 index 00000000000..e649abf28b3 --- /dev/null +++ b/test/jdk/sun/security/ssl/X509TrustManagerImpl/Entrust/entrustrootcag4-chain.pem @@ -0,0 +1,92 @@ +Root Certificate: + Version: 3 (0x2) + Serial Number: + d9:b5:43:7f:af:a9:39:0f:00:00:00:00:55:65:ad:58 + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=US, O=Entrust, Inc., OU=See www.entrust.net/legal-terms, OU=(c) 2015 Entrust, Inc. - for authorized use only, CN=Entrust Root Certification Authority - G4 + Validity + Not Before: May 27 11:11:16 2015 GMT + Not After : Dec 27 11:41:16 2037 GMT + +-----BEGIN CERTIFICATE----- +MIIIIzCCBwugAwIBAgIQDD4I8FgD7+DVcBLMBwa39jANBgkqhkiG9w0BAQsFADCB +ujELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xKDAmBgNVBAsT +H1NlZSB3d3cuZW50cnVzdC5uZXQvbGVnYWwtdGVybXMxOTA3BgNVBAsTMChjKSAy +MDE0IEVudHJ1c3QsIEluYy4gLSBmb3IgYXV0aG9yaXplZCB1c2Ugb25seTEuMCwG +A1UEAxMlRW50cnVzdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEwxTjAeFw0y +NDA2MjgyMTQzNTRaFw0yNTA3MjgyMTQzNTNaMIHLMQswCQYDVQQGEwJDQTEQMA4G +A1UECBMHT250YXJpbzEPMA0GA1UEBxMGT3R0YXdhMRMwEQYLKwYBBAGCNzwCAQMT +AkNBMRgwFgYLKwYBBAGCNzwCAQITB09udGFyaW8xGDAWBgNVBAoTD0VudHJ1c3Qg +TGltaXRlZDEdMBsGA1UEDxMUUHJpdmF0ZSBPcmdhbml6YXRpb24xEzARBgNVBAUT +CjEwMDA0OTI4NzkxHDAaBgNVBAMTE3ZhbGlkZzQuZW50cnVzdC5uZXQwggIiMA0G +CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCfUHGdeme0jraIiUzPYtuX1G9rlCU1 +eKDqDbsgp7VIS7rI/VgbsS7oKnE6KHP+qGrXRhYdvFLFDa+REY6fVOWkLuTXhVLb +5C7ym2pi0OUMKvrGtDLUxlHiEAmkmjPDl6TLMTDrLgWOLFMRzyeTcxnZtMrxUnAf +yzSPlqm1bkN/oRp2EOiXvuSbci8UA0QswV6g8EUbRB0qyv6OophoaQYo/+KRwTJT +k6S8YDsEJnlDb8tjEhfIUjp2Md5ThBxf5Ib29aXebZ5HFh2x5VPrzOwDUPk0fVNM +pWFfiX79RW6w5Vei5qtretLohbw6b5aJmaJ1LweAEkIlhy5eUuuG6v8Efm8JSAle +eKMtflTigmayaWMVCd2GeB6LajcflAw7BUU2brRMJwMpaeXXhL/mVpjbev/5TtVD ++H9IlW3PMyQnUJc0YuUVmdi1eOM5qoQaQE4BDPHz2G41eDgT8J9Gb1FX5mT+9l2I +iJD47pwcBIw5tHCn2nuz1+8CDuYpfH2+t2LPFHVI15h1scGotZvzUJ5TzPdQqZI7 +K2LTL49Zs2HsObrGr07Vj28WyzkjIfTrVSV/29hgz1zVjUa0uyTeOzrc3VIg7NTv +RoMTTYuUeUoMSmFQ8z9CSGh7cxFlrhGjFO+66++JFNwakAEp7kS5c2qTLaapY9dM +8UMIr5951z994QIDAQABo4IDEDCCAwwwDAYDVR0TAQH/BAIwADAdBgNVHQ4EFgQU +/EjjpmMa/SepMqPlglXS5AbGcScwHwYDVR0jBBgwFoAU7kfRhXHx/S23P7s+Y1h3 +F0lADpUwaAYIKwYBBQUHAQEEXDBaMCMGCCsGAQUFBzABhhdodHRwOi8vb2NzcC5l +bnRydXN0Lm5ldDAzBggrBgEFBQcwAoYnaHR0cDovL2FpYS5lbnRydXN0Lm5ldC9s +MW4tY2hhaW4yNTYuY2VyMDMGA1UdHwQsMCowKKAmoCSGImh0dHA6Ly9jcmwuZW50 +cnVzdC5uZXQvbGV2ZWwxbi5jcmwwHgYDVR0RBBcwFYITdmFsaWRnNC5lbnRydXN0 +Lm5ldDAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwIGCCsGAQUF +BwMBMEsGA1UdIAREMEIwBwYFZ4EMAQEwNwYKYIZIAYb6bAoBAjApMCcGCCsGAQUF +BwIBFhtodHRwczovL3d3dy5lbnRydXN0Lm5ldC9ycGEwggF/BgorBgEEAdZ5AgQC +BIIBbwSCAWsBaQB2ABLxTjS9U3JMhAYZw48/ehP457Vih4icbTAFhOvlhiY6AAAB +kGDOC9YAAAQDAEcwRQIgWhFWhf2sBQ3ufMH0yubwLDt+3f/b5rScs09o1YEjg6MC +IQDpkgEMWBAM+NV2aCnC8QH+RH6xBqhPPt6JZTm3W+vHkwB3ABoE/0nQVB1Ar/ag +w7/x2MRnL07s7iNAaJhrF0Au3Il9AAABkGDODBQAAAQDAEgwRgIhAOgp+oas+jBr +9wOBo0QDdVQGmP8KJupfRf/MDKO+kSRjAiEA9JnEHTbFHre2TS9habVJA/3jM/t5 +CKtixwQqdpLXQUAAdgAN4fIwK9MNwUBiEgnqVS78R3R8sdfpMO8OQh60fk6qNAAA +AZBgzgwVAAAEAwBHMEUCIBOYI8rl87VepcPQlaGh6AbKhKw1UlbxIf7etR/d2M47 +AiEAkFXOVvzkP6kX/z1yRneYn0mlPbDvAFLsSDghl/gkdtYwDQYJKoZIhvcNAQEL +BQADggEBAJovgoheNHFBUpnodfOiKtpRo8AE6dLuOX1H2uRHiDg0Gza0/w95KkEE +BqjKmJIbJrs2TQJnkM0LjaubHn1TP4XC40qieMXB4ylJzC5FWDZBqMHZmLTvVY01 +irBMyub0On8d1BlEquD2r3KHQFnyUvi/uxzbNJOVbNJYglKhTI+UfcXk7zpHmNG+ ++SbBkpJkuqQ9ujG1K25FRa/01j1p4ZlDrJ3KCT7fDEf10TN0u5VX6moVT9cRVR2U +gX16BV8m/hoJVTD0fBCKIKjtklS//b+Jr49uxWFulrDwlRKyDWmBXLnqsZvpCobi +deDsWiUkcvd+DjNgpDTEHCTrXXjd8tU= +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIGMjCCBBqgAwIBAgIRAKvsd/8bQQwHAAAAAFVl2AUwDQYJKoZIhvcNAQELBQAw +gb4xCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQL +Ex9TZWUgd3d3LmVudHJ1c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykg +MjAxNSBFbnRydXN0LCBJbmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxMjAw +BgNVBAMTKUVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEc0 +MB4XDTE3MTEyMjIwMDQyMFoXDTMwMTIyMjIwMzQyMFowgboxCzAJBgNVBAYTAlVT +MRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMSgwJgYDVQQLEx9TZWUgd3d3LmVudHJ1 +c3QubmV0L2xlZ2FsLXRlcm1zMTkwNwYDVQQLEzAoYykgMjAxNCBFbnRydXN0LCBJ +bmMuIC0gZm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxLjAsBgNVBAMTJUVudHJ1c3Qg +Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBMMU4wggEiMA0GCSqGSIb3DQEBAQUA +A4IBDwAwggEKAoIBAQDcSG+caYQ4xcvf+dt8bgCEHorO0g5j0H1NOtQzRXgUoG8y +QuRbJX9swyKqQZbsc18YvTV8OKA/uSNE46Jvq47TFPojWWTVLbNDqpM07e4EFYKs +A9NFzAUngijnf3ivnXA6iNPAMXaEhXmhY/YFjk8NoM7Y1PFsA0oj5hamKQ06iO/j +gvBScLmnQ1ju9Qj9IGIg18UL5AJNw0frspLUQBYVrLGaqAy5Nl2BUJKaZ4vnSLvP +nk6YrB15mo1phHae10Ba4fx7R3z8IZ/hby4OXTy/KZpu107VEQPAwTuDK8ZXxB5y +0DSzi4vaw27aLrUsq4aFqUo03gEfC31vWW76TNkFAgMBAAGjggErMIIBJzAOBgNV +HQ8BAf8EBAMCAQYwEgYDVR0TAQH/BAgwBgEB/wIBADAdBgNVHSUEFjAUBggrBgEF +BQcDAQYIKwYBBQUHAwIwOwYDVR0gBDQwMjAwBgRVHSAAMCgwJgYIKwYBBQUHAgEW +Gmh0dHA6Ly93d3cuZW50cnVzdC5uZXQvcnBhMDMGCCsGAQUFBwEBBCcwJTAjBggr +BgEFBQcwAYYXaHR0cDovL29jc3AuZW50cnVzdC5uZXQwMAYDVR0fBCkwJzAloCOg +IYYfaHR0cDovL2NybC5lbnRydXN0Lm5ldC9nNGNhLmNybDAdBgNVHQ4EFgQU7kfR +hXHx/S23P7s+Y1h3F0lADpUwHwYDVR0jBBgwFoAUnzjEViPDOeigcWzoVEzk6Dqx +v2cwDQYJKoZIhvcNAQELBQADggIBACMeFFgsWmC7h6D1v8DJUkOpm/m5UhVhO0hb +pQMQKMhKkl744Y9SWG4WNmpQy743TTciEJPZFhc7ke2R6VmK8ZJUqro2awOw1RWZ +OtHla59Btf1NQd41vOVdU+qFhs8lFfXg9sK7YHTrfxHtMXLoGnkkamK3xJgn7sXa +/zUvUDBTpDCXcpO9SyHoKIQswmkIPpRyIdPF4biRdR3N+9MYmlfqN/Nk3OEZ73xZ +AUZP6Gu+f9cEiHTA8NdYHCPLJWyFnIHWK+QuTFEnKYnOYxCeroLBNOO64e8JWZ39 +kZ22BBXhHzqOCCczS7JOJTRF+JgvWuxbFwRstj8qf3fE+JndWmq2FC4hTHtpuK5K +ENuiRm5gdkXfsXmB+qB6y5gaajiTIMscGIcZIKTe2YdKrLoicvEz8k+loM7favik +vzFioTNTDHYGx3mkfElBE7ycY8n+jZE3QBBv33k28MeQi7XNgEaMc4tYwoZIdE9A +xVccXTzEQzka82dOkRB1dU0XZId9XAWv+CtNc2TjF6Wgx2seA/c6H8S0IfgQBIV2 +8iN2wZns2QFdawkdy3hMUqPnA++kuGhLW3GemsIY5dP/WxY8rd+OfLb/Ks9T1pCd +28t7PQRcQsgkYmouzrOW9ASBvYqLLdhl4y+fFXff8RkPIKMNoYP06WJvRKmky9R/ +41/nXRas +-----END CERTIFICATE----- diff --git a/test/jdk/sun/security/x509/URICertStore/SocksProxy.java b/test/jdk/sun/security/x509/URICertStore/SocksProxy.java index a44cf603124..67a372b97b3 100644 --- a/test/jdk/sun/security/x509/URICertStore/SocksProxy.java +++ b/test/jdk/sun/security/x509/URICertStore/SocksProxy.java @@ -22,6 +22,7 @@ */ import java.io.IOException; +import java.net.InetAddress; import java.net.ServerSocket; import java.net.Socket; import java.util.Objects; @@ -30,7 +31,7 @@ import javax.net.ServerSocketFactory; /* - * A simple socks4 proxy for traveling socket. + * A simple socks proxy for traveling socket. */ class SocksProxy implements Runnable, AutoCloseable { @@ -49,10 +50,11 @@ static SocksProxy startProxy(Consumer socketConsumer) ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(0); - System.setProperty("socksProxyHost", "127.0.0.1"); + System.setProperty("socksProxyHost", + InetAddress.getLoopbackAddress().getHostAddress()); System.setProperty("socksProxyPort", String.valueOf(server.getLocalPort())); - System.setProperty("socksProxyVersion", "4"); + System.setProperty("socksProxyVersion", "5"); SocksProxy proxy = new SocksProxy(server, socketConsumer); Thread proxyThread = new Thread(proxy, "Proxy"); diff --git a/test/jdk/tools/launcher/Settings.java b/test/jdk/tools/launcher/Settings.java index 76e62ffbe57..e65cceaf1fe 100644 --- a/test/jdk/tools/launcher/Settings.java +++ b/test/jdk/tools/launcher/Settings.java @@ -25,7 +25,7 @@ /* * @test - * @bug 6994753 7123582 8305950 + * @bug 6994753 7123582 8305950 8310201 * @summary tests -XshowSettings options * @modules jdk.compiler * jdk.zipfs @@ -67,6 +67,9 @@ static void checkNotContains(TestResult tr, String str) { private static final String VM_SETTINGS = "VM settings:"; private static final String PROP_SETTINGS = "Property settings:"; private static final String LOCALE_SETTINGS = "Locale settings:"; + private static final String LOCALE_SUMMARY_SETTINGS = + "Locale settings summary:"; + private static final String AVAILABLE_LOCALES = "available locales"; private static final String SYSTEM_SETTINGS = "Operating System Metrics:"; private static final String STACKSIZE_SETTINGS = "Stack Size:"; private static final String TZDATA_SETTINGS = "tzdata version"; @@ -74,7 +77,9 @@ static void checkNotContains(TestResult tr, String str) { static void containsAllOptions(TestResult tr) { checkContains(tr, VM_SETTINGS); checkContains(tr, PROP_SETTINGS); - checkContains(tr, LOCALE_SETTINGS); + checkNotContains(tr, LOCALE_SETTINGS); + checkNotContains(tr, AVAILABLE_LOCALES); + checkContains(tr, LOCALE_SUMMARY_SETTINGS); checkContains(tr, TZDATA_SETTINGS); if (System.getProperty("os.name").contains("Linux")) { checkContains(tr, SYSTEM_SETTINGS); @@ -141,6 +146,8 @@ static void runTestOptionLocale() throws IOException { checkNotContains(tr, VM_SETTINGS); checkNotContains(tr, PROP_SETTINGS); checkContains(tr, LOCALE_SETTINGS); + checkContains(tr, AVAILABLE_LOCALES); + checkNotContains(tr, LOCALE_SUMMARY_SETTINGS); checkContains(tr, TZDATA_SETTINGS); } diff --git a/test/jtreg-ext/requires/VMProps.java b/test/jtreg-ext/requires/VMProps.java index c31290ac525..6dfbcfd337c 100644 --- a/test/jtreg-ext/requires/VMProps.java +++ b/test/jtreg-ext/requires/VMProps.java @@ -46,6 +46,8 @@ import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; import sun.hotspot.code.Compiler; import sun.hotspot.cpuinfo.CPUInfo; @@ -80,6 +82,10 @@ public void put(String key, Supplier s) { } map.put(key, value); } + + public void putAll(Map map) { + map.entrySet().forEach(e -> put(e.getKey(), () -> e.getValue())); + } } /** @@ -123,6 +129,7 @@ public Map call() { map.put("vm.musl", this::isMusl); map.put("release.implementor", this::implementor); map.put("vm.flagless", this::isFlagless); + map.putAll(xOptFlags()); // -Xmx4g -> @requires vm.opt.x.Xmx == "4g" ) vmGC(map); // vm.gc.X = true/false vmOptFinalFlags(map); @@ -582,9 +589,7 @@ private String isFlagless() { return "" + "true".equalsIgnoreCase(flagless); } - List allFlags = new ArrayList(); - Collections.addAll(allFlags, System.getProperty("test.vm.opts", "").trim().split("\\s+")); - Collections.addAll(allFlags, System.getProperty("test.java.opts", "").trim().split("\\s+")); + List allFlags = allFlags().collect(Collectors.toList()); // check -XX flags var ignoredXXFlags = Set.of( @@ -627,6 +632,35 @@ private String isFlagless() { return "" + result; } + private Stream allFlags() { + return Stream.of((System.getProperty("test.vm.opts", "") + " " + System.getProperty("test.java.opts", "")).trim().split("\\s+")); + } + + /** + * Parses extra options, options that start with -X excluding the + * bare -X option (as it is not considered an extra option). + * Ignores extra options not starting with -X + * + * This could be improved to handle extra options not starting + * with -X as well as "standard" options. + */ + private Map xOptFlags() { + return allFlags() + .filter(s -> s.startsWith("-X") && !s.startsWith("-XX:") && !s.equals("-X")) + .map(s -> s.replaceFirst("-", "")) + .map(flag -> { + String[] split = flag.split("[:0123456789]", 2); + return split.length == 2 ? new String[] {split[0], flag.substring(split[0].length(), flag.length() - split[1].length()), split[1]} + : split; + }) + .collect(Collectors.toMap(a -> "vm.opt.x." + a[0], + a -> (a.length == 1) + ? "true" // -Xnoclassgc + : (a[1].equals(":") + ? a[2] // ["-XshowSettings", ":", "system"] + : a[1] + a[2]))); // ["-Xmx", "4", "g"] + } + /** * Dumps the map to the file if the file name is given as the property. * This functionality could be helpful to know context in the real diff --git a/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java b/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java index 48106face35..d8539b8c656 100644 --- a/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java +++ b/test/langtools/jdk/internal/shellsupport/doc/JavadocHelperTest.java @@ -30,7 +30,7 @@ * jdk.compiler/com.sun.tools.javac.main * jdk.compiler/jdk.internal.shellsupport.doc * @build toolbox.ToolBox toolbox.JarTask toolbox.JavacTask - * @run testng/timeout=900/othervm JavadocHelperTest + * @run testng/timeout=900/othervm -Xmx1024m JavadocHelperTest */ import java.io.IOException; diff --git a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java index aa607d29598..bc875394442 100644 --- a/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java +++ b/test/langtools/jdk/javadoc/doclet/testSearch/TestSearch.java @@ -400,7 +400,7 @@ void checkSearchOutput(String fileName, boolean expectedOutput, boolean moduleDi "\n", - "\n", + "\n", "", "var pathtoroot = \"./\";\n" + "var useModuleDirectories = " + moduleDirectoriesVar + ";\n" @@ -593,7 +593,7 @@ void checkJqueryAndImageFiles(boolean expectedOutput) { checkFiles(expectedOutput, "search.js", "jquery-ui.overrides.css", - "jquery/jquery-3.6.1.min.js", + "jquery/jquery-3.7.1.min.js", "jquery/jquery-ui.min.js", "jquery/jquery-ui.min.css", "jquery/external/jquery/jquery.js", diff --git a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java index 23b48e23dac..f6712582178 100644 --- a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java +++ b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java @@ -200,7 +200,7 @@ protected void error(String msg) { "help-doc.html", "index-all.html", "index.html", - "jquery/jquery-3.6.1.min.js", + "jquery/jquery-3.7.1.min.js", "jquery/jquery-ui.min.js", "jquery/jquery-ui.min.css", "jquery/external/jquery/jquery.js", diff --git a/test/langtools/jdk/jshell/AnalyzeSnippetTest.java b/test/langtools/jdk/jshell/AnalyzeSnippetTest.java index b566a023caf..3e2e1a839e2 100644 --- a/test/langtools/jdk/jshell/AnalyzeSnippetTest.java +++ b/test/langtools/jdk/jshell/AnalyzeSnippetTest.java @@ -64,6 +64,7 @@ public void setUp() { state = JShell.builder() .out(new PrintStream(new ByteArrayOutputStream())) .err(new PrintStream(new ByteArrayOutputStream())) + .executionEngine(Presets.TEST_DEFAULT_EXECUTION) .build(); sca = state.sourceCodeAnalysis(); } diff --git a/test/langtools/jdk/jshell/CustomInputToolBuilder.java b/test/langtools/jdk/jshell/CustomInputToolBuilder.java index a80f58daabe..523981b3d91 100644 --- a/test/langtools/jdk/jshell/CustomInputToolBuilder.java +++ b/test/langtools/jdk/jshell/CustomInputToolBuilder.java @@ -35,6 +35,7 @@ import java.io.InputStream; import java.io.PrintStream; import java.util.Arrays; +import java.util.HashMap; import java.util.List; import jdk.jshell.tool.JavaShellToolBuilder; import org.testng.annotations.Test; @@ -88,7 +89,9 @@ private void doTest(boolean interactiveTerminal, String code, String... expected .out(printOut, printOut, printOut) .interactiveTerminal(interactiveTerminal) .promptCapture(true) - .start("--no-startup"); + .persistence(new HashMap<>()) + .start("--no-startup", + "--execution", Presets.TEST_DEFAULT_EXECUTION); String actual = new String(out.toByteArray()); List actualLines = Arrays.asList(actual.split("\\R")); diff --git a/test/langtools/jdk/jshell/ExecutionControlTestBase.java b/test/langtools/jdk/jshell/ExecutionControlTestBase.java index 201150797f5..9b2a4f34ebe 100644 --- a/test/langtools/jdk/jshell/ExecutionControlTestBase.java +++ b/test/langtools/jdk/jshell/ExecutionControlTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, 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,28 +25,14 @@ import org.testng.annotations.Test; import jdk.jshell.VarSnippet; -import java.net.InetAddress; import static jdk.jshell.Snippet.Status.VALID; import static jdk.jshell.Snippet.SubKind.*; public class ExecutionControlTestBase extends KullaTesting { - String standardListenSpec() { - String loopback = InetAddress.getLoopbackAddress().getHostAddress(); - return "jdi:hostname(" + loopback + ")"; - } - - String standardLaunchSpec() { - return "jdi:launch(true)"; - } - - String standardJdiSpec() { - return "jdi"; - } - - String standardSpecs() { - return "5(" + standardListenSpec() + "), 6(" + standardLaunchSpec() + "), 7(" + standardJdiSpec() + ")"; + String alwaysPassingSpec() { + return "5(local)"; } @Test diff --git a/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java b/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java index da838798f8e..a094ed4a86f 100644 --- a/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java +++ b/test/langtools/jdk/jshell/FailOverDirectExecutionControlTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, 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 @@ -129,9 +129,7 @@ public void setUp() { Map pm = provider.defaultParameters(); pm.put("0", "alwaysFailing"); pm.put("1", "alwaysFailing"); - pm.put("2", standardListenSpec()); - pm.put("3", standardLaunchSpec()); - pm.put("4", standardJdiSpec()); + pm.put("2", "local"); setUp(builder -> builder.executionEngine(provider, pm)); } @@ -159,9 +157,7 @@ public void variables() { assertTrue(log.contains("This operation intentionally broken"), log); log = logged.get(Level.FINEST).get(0); assertTrue( - log.contains("Success failover -- 2 = " + standardListenSpec()) - || log.contains("Success failover -- 3 = " + standardLaunchSpec()) - || log.contains("Success failover -- 4 = " + standardJdiSpec()), + log.contains("Success failover -- 2 = local"), log); } } diff --git a/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java b/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java index f3218fab7c7..31011960880 100644 --- a/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java +++ b/test/langtools/jdk/jshell/FailOverExecutionControlDyingLaunchTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, 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 @@ -43,6 +43,6 @@ public class FailOverExecutionControlDyingLaunchTest extends ExecutionControlTes public void setUp() { setUp(builder -> builder.executionEngine( "failover:0(jdi:remoteAgent(DyingRemoteAgent),launch(true)), " - + standardSpecs())); + + alwaysPassingSpec())); } } diff --git a/test/langtools/jdk/jshell/FailOverExecutionControlHangingLaunchTest.java b/test/langtools/jdk/jshell/FailOverExecutionControlHangingLaunchTest.java index 778d004915c..9958b7a3284 100644 --- a/test/langtools/jdk/jshell/FailOverExecutionControlHangingLaunchTest.java +++ b/test/langtools/jdk/jshell/FailOverExecutionControlHangingLaunchTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, 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 @@ -42,6 +42,6 @@ public class FailOverExecutionControlHangingLaunchTest extends ExecutionControlT public void setUp() { setUp(builder -> builder.executionEngine( "failover:0(jdi:remoteAgent(HangingRemoteAgent),launch(true)), " - + standardSpecs())); + + alwaysPassingSpec())); } } diff --git a/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java b/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java index f22dd821f40..4f29bfe9c7a 100644 --- a/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java +++ b/test/langtools/jdk/jshell/FailOverExecutionControlHangingListenTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, 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 @@ -45,6 +45,6 @@ public void setUp() { String loopback = InetAddress.getLoopbackAddress().getHostAddress(); setUp(builder -> builder.executionEngine( "failover:0(jdi:remoteAgent(HangingRemoteAgent),hostname(" + loopback + "))," - + standardSpecs())); + + alwaysPassingSpec())); } } diff --git a/test/langtools/jdk/jshell/FailOverExecutionControlTest.java b/test/langtools/jdk/jshell/FailOverExecutionControlTest.java index 0843351815f..80dc56d72c4 100644 --- a/test/langtools/jdk/jshell/FailOverExecutionControlTest.java +++ b/test/langtools/jdk/jshell/FailOverExecutionControlTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2023, 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 @@ -41,7 +41,7 @@ public class FailOverExecutionControlTest extends ExecutionControlTestBase { @Override public void setUp() { setUp(builder -> builder.executionEngine("failover:0(expectedFailureNonExistent1), 1(expectedFailureNonExistent2), " - + standardSpecs())); + + alwaysPassingSpec())); } } diff --git a/test/langtools/jdk/jshell/IdGeneratorTest.java b/test/langtools/jdk/jshell/IdGeneratorTest.java index 23727aef643..e8a38dfe7f0 100644 --- a/test/langtools/jdk/jshell/IdGeneratorTest.java +++ b/test/langtools/jdk/jshell/IdGeneratorTest.java @@ -53,7 +53,8 @@ public JShell.Builder getBuilder() { return JShell.builder() .in(inStream) .out(new PrintStream(outStream)) - .err(new PrintStream(errStream)); + .err(new PrintStream(errStream)) + .executionEngine(Presets.TEST_DEFAULT_EXECUTION); } public void testTempNameGenerator() { diff --git a/test/langtools/jdk/jshell/KullaTesting.java b/test/langtools/jdk/jshell/KullaTesting.java index 369b2ed1f44..d74f3484f4b 100644 --- a/test/langtools/jdk/jshell/KullaTesting.java +++ b/test/langtools/jdk/jshell/KullaTesting.java @@ -100,7 +100,9 @@ public class KullaTesting { private Set allSnippets = new LinkedHashSet<>(); static { - JShell js = JShell.create(); + JShell js = JShell.builder() + .executionEngine(Presets.TEST_DEFAULT_EXECUTION) + .build(); MAIN_SNIPPET = js.eval("MAIN_SNIPPET").get(0).snippet(); js.close(); assertTrue(MAIN_SNIPPET != null, "Bad MAIN_SNIPPET set-up -- must not be null"); @@ -192,7 +194,8 @@ public int read(byte[] b, int off, int len) throws IOException { JShell.Builder builder = JShell.builder() .in(in) .out(new PrintStream(outStream)) - .err(new PrintStream(errStream)); + .err(new PrintStream(errStream)) + .executionEngine(Presets.TEST_DEFAULT_EXECUTION); bc.accept(builder); state = builder.build(); allSnippets = new LinkedHashSet<>(); diff --git a/test/langtools/jdk/jshell/Presets.java b/test/langtools/jdk/jshell/Presets.java new file mode 100644 index 00000000000..b9a93c967dc --- /dev/null +++ b/test/langtools/jdk/jshell/Presets.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2023, 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.net.InetAddress; +import java.util.*; + +public class Presets { + public static final String TEST_DEFAULT_EXECUTION; + public static final String TEST_STANDARD_EXECUTION; + + static { + String loopback = InetAddress.getLoopbackAddress().getHostAddress(); + + TEST_DEFAULT_EXECUTION = "failover:0(jdi:hostname(" + loopback + "))," + + "1(jdi:launch(true)), 2(jdi), 3(local)"; + TEST_STANDARD_EXECUTION = "failover:0(jdi:hostname(" + loopback + "))," + + "1(jdi:launch(true)), 2(jdi)"; + } + + public static String[] addExecutionIfMissing(String[] args) { + if (Arrays.stream(args).noneMatch(Presets::remoteRelatedOption)) { + List augmentedArgs = new ArrayList<>(); + + augmentedArgs.add("--execution"); + augmentedArgs.add(Presets.TEST_DEFAULT_EXECUTION); + augmentedArgs.addAll(List.of(args)); + + return augmentedArgs.toArray(s -> new String[s]); + } + + return args; + } + + private static boolean remoteRelatedOption(String option) { + return "--execution".equals(option) || + "--add-modules".equals(option) || + option.startsWith("-R"); + } +} diff --git a/test/langtools/jdk/jshell/ReplToolTesting.java b/test/langtools/jdk/jshell/ReplToolTesting.java index 5ef4dc2990c..85b7beff97c 100644 --- a/test/langtools/jdk/jshell/ReplToolTesting.java +++ b/test/langtools/jdk/jshell/ReplToolTesting.java @@ -292,7 +292,7 @@ protected JavaShellToolBuilder builder(Locale locale) { private void testRaw(Locale locale, String[] args, ReplTest... tests) { testRawInit(tests); - testRawRun(locale, args); + testRawRun(locale, Presets.addExecutionIfMissing(args)); testRawCheck(locale); } diff --git a/test/langtools/jdk/jshell/StartOptionTest.java b/test/langtools/jdk/jshell/StartOptionTest.java index df445d49750..aa8d9be03a9 100644 --- a/test/langtools/jdk/jshell/StartOptionTest.java +++ b/test/langtools/jdk/jshell/StartOptionTest.java @@ -81,7 +81,7 @@ private JavaShellToolBuilder builder() { protected int runShell(String... args) { try { return builder() - .start(args); + .start(Presets.addExecutionIfMissing(args)); } catch (Exception ex) { fail("Repl tool died with exception", ex); } diff --git a/test/langtools/jdk/jshell/ToolReloadTest.java b/test/langtools/jdk/jshell/ToolReloadTest.java index 13d583e51f5..4709584cd12 100644 --- a/test/langtools/jdk/jshell/ToolReloadTest.java +++ b/test/langtools/jdk/jshell/ToolReloadTest.java @@ -201,7 +201,7 @@ public void testReloadCrashRestore() { } public void testEnvBadModule() { - test( + test(new String[] {"--execution", Presets.TEST_STANDARD_EXECUTION}, (a) -> assertVariable(a, "int", "x", "5", "5"), (a) -> assertMethod(a, "int m(int z) { return z * z; }", "(int)int", "m"), diff --git a/test/langtools/jdk/jshell/UITesting.java b/test/langtools/jdk/jshell/UITesting.java index 848c0d52797..477e540e716 100644 --- a/test/langtools/jdk/jshell/UITesting.java +++ b/test/langtools/jdk/jshell/UITesting.java @@ -93,7 +93,8 @@ protected void doRunTest(Test test) throws Exception { .promptCapture(true) .persistence(new HashMap<>()) .locale(Locale.US) - .run("--no-startup"); + .run("--no-startup", + "--execution", Presets.TEST_DEFAULT_EXECUTION); } catch (Exception ex) { throw new IllegalStateException(ex); } diff --git a/test/langtools/tools/javadoc/api/basic/APITest.java b/test/langtools/tools/javadoc/api/basic/APITest.java index 23b48e23dac..f6712582178 100644 --- a/test/langtools/tools/javadoc/api/basic/APITest.java +++ b/test/langtools/tools/javadoc/api/basic/APITest.java @@ -200,7 +200,7 @@ protected void error(String msg) { "help-doc.html", "index-all.html", "index.html", - "jquery/jquery-3.6.1.min.js", + "jquery/jquery-3.7.1.min.js", "jquery/jquery-ui.min.js", "jquery/jquery-ui.min.css", "jquery/external/jquery/jquery.js", diff --git a/test/lib-test/jdk/test/lib/apps/LingeredAppTest.java b/test/lib-test/jdk/test/lib/apps/LingeredAppTest.java index 54a3706fa7c..5f03fa4c4a8 100644 --- a/test/lib-test/jdk/test/lib/apps/LingeredAppTest.java +++ b/test/lib-test/jdk/test/lib/apps/LingeredAppTest.java @@ -24,9 +24,9 @@ /* * @test * @summary Unit test for LingeredApp - * @compile LingeredAppTest.java - * @compile LingeredApp.java - * @run main LingeredAppTest + * @library /test/lib + * @build jdk.test.lib.apps.LingeredAppTest jdk.test.lib.apps.LingeredApp + * @run main jdk.test.lib.apps.LingeredAppTest */ package jdk.test.lib.apps; diff --git a/test/lib-test/jdk/test/lib/hexdump/HexPrinterTest.java b/test/lib-test/jdk/test/lib/hexdump/HexPrinterTest.java index bad85a1e624..ccaf666c256 100644 --- a/test/lib-test/jdk/test/lib/hexdump/HexPrinterTest.java +++ b/test/lib-test/jdk/test/lib/hexdump/HexPrinterTest.java @@ -88,12 +88,22 @@ Object[][] builtinParams() { public void testBuiltins(String name, String offsetFormat, String binFormat, int colWidth, String annoDelim, int annoWidth, HexPrinter.Formatter mapper, String lineSep) { - HexPrinter f = switch (name) { - case "minimal" -> HexPrinter.minimal(); - case "simple" -> HexPrinter.simple(); - case "canonical" -> HexPrinter.canonical(); - case "source" -> HexPrinter.source(); - default -> throw new IllegalStateException("Unexpected value: " + name); + HexPrinter f; + switch (name) { + case "minimal": + f = HexPrinter.minimal(); + break; + case "simple": + f = HexPrinter.simple(); + break; + case "canonical": + f = HexPrinter.canonical(); + break; + case "source": + f = HexPrinter.source(); + break; + default: + throw new IllegalStateException("Unexpected value: " + name); }; testParams(f, offsetFormat, binFormat, colWidth, annoDelim, annoWidth, mapper, lineSep); diff --git a/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java b/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java index 508c17fc399..fc3b793c47a 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerRunOptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2024, 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 @@ -60,6 +60,9 @@ public DockerRunOptions(String imageNameAndTag, String javaCmd, this.command = javaCmd; this.classToRun = classToRun; this.addJavaOpts(javaOpts); + // always print hserr to stderr in the docker tests to avoid + // trouble accessing it after a crash in the container + this.addJavaOpts("-XX:+ErrorFileToStderr"); } public DockerRunOptions addDockerOpts(String... opts) { diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index ecf9bc6db7e..6be5aacebd5 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -208,7 +208,7 @@ private static void buildImage(String imageName, Path buildDir) throws Exception /** * Build the docker command to run java inside a container * - * @param DockerRunOptions optins for running docker + * @param DockerRunOptions options for running docker * * @return command * @throws Exception @@ -242,7 +242,7 @@ public static List buildJavaCommand(DockerRunOptions opts) throws Except /** * Run Java inside the docker image with specified parameters and options. * - * @param DockerRunOptions optins for running docker + * @param DockerRunOptions options for running docker * * @return output of the run command * @throws Exception @@ -255,7 +255,7 @@ public static OutputAnalyzer dockerRunJava(DockerRunOptions opts) throws Excepti /** * Remove docker image * - * @param DockerRunOptions optins for running docker + * @param DockerRunOptions options for running docker * @throws Exception */ public static void removeDockerImage(String imageNameAndTag) throws Exception { diff --git a/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java b/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java index 0e833cd9115..acac0bde33d 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerfileConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2024, 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 @@ -63,6 +63,11 @@ static String getBaseImageVersion() { return version; } + // Ubuntu 22.04 ppc started to crash in libz inflateReset on Power8 based host + // those recent Ubuntu versions only work on Power9+ + if (Platform.isPPC()) { + return "20.04"; + } return "latest"; } }