diff --git a/.hgtags b/.hgtags index cb3ba5ed43e..1cb41f0429d 100644 --- a/.hgtags +++ b/.hgtags @@ -269,3 +269,7 @@ c5495e25c7258ab5f96a1ae14610887d76d2be63 jdk9-b18 d9ce05f36ffec3e5e8af62a92455c1c66a63c320 jdk9-b24 13a5c76976fe48e55c9727c25fae2d2ce7c05da0 jdk9-b25 cd6f4557e7fea5799ff3762ed7a80a743e75d5fd jdk9-b26 +d06a6d3c66c08293b2a9650f3cc01fd55c620e65 jdk9-b27 +f4269e8f454eb77763ecee228a88ae102a9aef6e jdk9-b28 +c36c0092693707a8255561433647e8c3cd724ccd jdk9-b29 +b2287cac7813c70ed7f679d9a46fe774bd4005f8 jdk9-b30 diff --git a/.hgtags-top-repo b/.hgtags-top-repo index d0fc930890e..0f468dba94d 100644 --- a/.hgtags-top-repo +++ b/.hgtags-top-repo @@ -269,3 +269,7 @@ ee4fd72b2ec3d92497f37163352f294aa695c6fb jdk9-b20 1d4a293fbec19dc2d5790bbb2c7dd0ed8f265484 jdk9-b24 aefd8899a8d6615fb34ba99b2e38996a7145baa8 jdk9-b25 d3ec8d048e6c3c46b6e0ee011cc551ad386dfba5 jdk9-b26 +ba5645f2735b41ed085d07ba20fa7b322afff318 jdk9-b27 +ea2f7981236f3812436958748ab3d26e80a35130 jdk9-b28 +9e6581aeda388a23fbee021fc33e6aa152a60657 jdk9-b29 +36e9bc875325813ac9c44ac0c617a463091fa9f5 jdk9-b30 diff --git a/Makefile b/Makefile index 1e574940964..d385e0f3299 100644 --- a/Makefile +++ b/Makefile @@ -108,12 +108,23 @@ else $(shell $(MKDIR) -p $(SJAVAC_SERVER_DIR) && $(RM) -rf $(SJAVAC_SERVER_DIR)/*) endif + # Split out the targets requiring sequential execution. Run these targets separately + # from the rest so that the rest may still enjoy full parallel execution. + SEQUENTIAL_TARGETS := $(filter dist-clean clean% reconfigure, $(MAIN_TARGETS)) + PARALLEL_TARGETS := $(filter-out $(SEQUENTIAL_TARGETS), $(MAIN_TARGETS)) + main-wrapper: - @$(if $(findstring clean, $(MAIN_TARGETS)), , $(call AtMakeStart)) - (cd $(root_dir)/make && $(BUILD_LOG_WRAPPER) $(MAKE) -f Main.gmk SPEC=$(SPEC) -j $(JOBS) \ - $(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(MAIN_TARGETS) \ - $(if $(filter true, $(OUTPUT_SYNC_SUPPORTED)), -O$(OUTPUT_SYNC))) - @$(if $(findstring clean, $(MAIN_TARGETS)), , $(call AtMakeEnd)) + ifneq ($(SEQUENTIAL_TARGETS), ) + (cd $(root_dir)/make && $(MAKE) -f Main.gmk SPEC=$(SPEC) -j 1 \ + $(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(SEQUENTIAL_TARGETS)) + endif + ifneq ($(PARALLEL_TARGETS), ) + @$(call AtMakeStart) + (cd $(root_dir)/make && $(BUILD_LOG_WRAPPER) $(MAKE) -f Main.gmk SPEC=$(SPEC) -j $(JOBS) \ + $(VERBOSE) VERBOSE=$(VERBOSE) LOG_LEVEL=$(LOG_LEVEL) $(PARALLEL_TARGETS) \ + $(if $(filter true, $(OUTPUT_SYNC_SUPPORTED)), -O$(OUTPUT_SYNC))) + @$(call AtMakeEnd) + endif .PHONY: main-wrapper @@ -136,8 +147,9 @@ help: $(info . make docs # Create all docs) $(info . make docs-javadoc # Create just javadocs, depends on less than full docs) $(info . make profiles # Create complete j2re compact profile images) - $(info . make bootcycle-images # Build images twice, second time with newly build JDK) + $(info . make bootcycle-images # Build images twice, second time with newly built JDK) $(info . make install # Install the generated images locally) + $(info . make reconfigure # Rerun configure with the same arguments as last time) $(info . make clean # Remove all files generated by make, but not those) $(info . # generated by configure) $(info . make dist-clean # Remove all files, including configuration) diff --git a/common/autoconf/basics.m4 b/common/autoconf/basics.m4 index 79d54a231ee..1a8cb100d94 100644 --- a/common/autoconf/basics.m4 +++ b/common/autoconf/basics.m4 @@ -377,7 +377,6 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], BASIC_REQUIRE_PROGS(CMP, cmp) BASIC_REQUIRE_PROGS(COMM, comm) BASIC_REQUIRE_PROGS(CP, cp) - BASIC_REQUIRE_PROGS(CPIO, cpio) BASIC_REQUIRE_PROGS(CUT, cut) BASIC_REQUIRE_PROGS(DATE, date) BASIC_REQUIRE_PROGS(DIFF, [gdiff diff]) @@ -427,6 +426,7 @@ AC_DEFUN_ONCE([BASIC_SETUP_FUNDAMENTAL_TOOLS], BASIC_PATH_PROGS(READLINK, [greadlink readlink]) BASIC_PATH_PROGS(DF, df) BASIC_PATH_PROGS(SETFILE, SetFile) + BASIC_PATH_PROGS(CPIO, [cpio bsdcpio]) ]) # Setup basic configuration paths, and platform-specific stuff related to PATHs. @@ -849,7 +849,12 @@ AC_DEFUN([BASIC_CHECK_FIND_DELETE], if test -f $DELETEDIR/TestIfFindSupportsDelete; then # No, it does not. rm $DELETEDIR/TestIfFindSupportsDelete - FIND_DELETE="-exec rm \{\} \+" + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + # AIX 'find' is buggy if called with '-exec {} \+' and an empty file list + FIND_DELETE="-print | xargs rm" + else + FIND_DELETE="-exec rm \{\} \+" + fi AC_MSG_RESULT([no]) else AC_MSG_RESULT([yes]) @@ -954,7 +959,7 @@ AC_DEFUN([BASIC_CHECK_DIR_ON_LOCAL_DISK], # not be the case in cygwin in certain conditions. AC_DEFUN_ONCE([BASIC_CHECK_SRC_PERMS], [ - if test x"$OPENJDK_BUILD_OS" = xwindows; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then file_to_test="$SRC_ROOT/LICENSE" if test `$STAT -c '%a' "$file_to_test"` -lt 400; then AC_MSG_ERROR([Bad file permissions on src files. This is usually caused by cloning the repositories with a non cygwin hg in a directory not created in cygwin.]) diff --git a/common/autoconf/basics_windows.m4 b/common/autoconf/basics_windows.m4 index 0d43553fd95..1bcb6151486 100644 --- a/common/autoconf/basics_windows.m4 +++ b/common/autoconf/basics_windows.m4 @@ -266,6 +266,14 @@ AC_DEFUN([BASIC_FIXUP_EXECUTABLE_MSYS], BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(new_path) new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + BASIC_WINDOWS_REWRITE_AS_UNIX_PATH(new_path) + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. diff --git a/common/autoconf/boot-jdk.m4 b/common/autoconf/boot-jdk.m4 index 872e33fb609..fbfa15c7b06 100644 --- a/common/autoconf/boot-jdk.m4 +++ b/common/autoconf/boot-jdk.m4 @@ -370,18 +370,27 @@ AC_DEFUN_ONCE([BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS], # Maximum amount of heap memory. # Maximum stack size. + JVM_MAX_HEAP=`expr $MEMORY_SIZE / 2` if test "x$BUILD_NUM_BITS" = x32; then - JVM_MAX_HEAP=1100M + if test "$JVM_MAX_HEAP" -gt "1100"; then + JVM_MAX_HEAP=1100 + elif test "$JVM_MAX_HEAP" -lt "512"; then + JVM_MAX_HEAP=512 + fi STACK_SIZE=768 else # Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit # pointers are used. Apparently, we need to increase the heap and stack # space for the jvm. More specifically, when running javac to build huge # jdk batch - JVM_MAX_HEAP=1600M + if test "$JVM_MAX_HEAP" -gt "1600"; then + JVM_MAX_HEAP=1600 + elif test "$JVM_MAX_HEAP" -lt "512"; then + JVM_MAX_HEAP=512 + fi STACK_SIZE=1536 fi - ADD_JVM_ARG_IF_OK([-Xmx$JVM_MAX_HEAP],boot_jdk_jvmargs_big,[$JAVA]) + ADD_JVM_ARG_IF_OK([-Xmx${JVM_MAX_HEAP}M],boot_jdk_jvmargs_big,[$JAVA]) ADD_JVM_ARG_IF_OK([-XX:ThreadStackSize=$STACK_SIZE],boot_jdk_jvmargs_big,[$JAVA]) AC_MSG_RESULT([$boot_jdk_jvmargs_big]) diff --git a/common/autoconf/build-performance.m4 b/common/autoconf/build-performance.m4 index 7d4b8abb8da..8425d744990 100644 --- a/common/autoconf/build-performance.m4 +++ b/common/autoconf/build-performance.m4 @@ -131,8 +131,8 @@ AC_DEFUN_ONCE([BPERF_SETUP_BUILD_JOBS], if test "x$with_jobs" = x; then # Number of jobs was not specified, calculate. AC_MSG_CHECKING([for appropriate number of jobs to run in parallel]) - # Approximate memory in GB, rounding up a bit. - memory_gb=`expr $MEMORY_SIZE / 1100` + # Approximate memory in GB. + memory_gb=`expr $MEMORY_SIZE / 1024` # Pick the lowest of memory in gb and number of cores. if test "$memory_gb" -lt "$NUM_CORES"; then JOBS="$memory_gb" @@ -291,16 +291,11 @@ AC_DEFUN_ONCE([BPERF_SETUP_SMART_JAVAC], AC_MSG_ERROR([Could not execute server java: $SJAVAC_SERVER_JAVA]) fi else - SJAVAC_SERVER_JAVA="" - # Hotspot specific options. - ADD_JVM_ARG_IF_OK([-verbosegc],SJAVAC_SERVER_JAVA,[$JAVA]) - # JRockit specific options. - ADD_JVM_ARG_IF_OK([-Xverbose:gc],SJAVAC_SERVER_JAVA,[$JAVA]) - SJAVAC_SERVER_JAVA="$JAVA $SJAVAC_SERVER_JAVA" + SJAVAC_SERVER_JAVA="$JAVA" fi AC_SUBST(SJAVAC_SERVER_JAVA) - if test "$MEMORY_SIZE" -gt "2500"; then + if test "$MEMORY_SIZE" -gt "3000"; then ADD_JVM_ARG_IF_OK([-d64],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) if test "$JVM_ARG_OK" = true; then JVM_64BIT=true @@ -308,34 +303,33 @@ AC_DEFUN_ONCE([BPERF_SETUP_SMART_JAVAC], fi fi + MX_VALUE=`expr $MEMORY_SIZE / 2` if test "$JVM_64BIT" = true; then - if test "$MEMORY_SIZE" -gt "17000"; then - ADD_JVM_ARG_IF_OK([-Xms10G -Xmx10G],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) + # Set ms lower than mx since more than one instance of the server might + # get launched at the same time before they figure out which instance won. + MS_VALUE=512 + if test "$MX_VALUE" -gt "2048"; then + MX_VALUE=2048 fi - if test "$MEMORY_SIZE" -gt "10000" && test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms6G -Xmx6G],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) - fi - if test "$MEMORY_SIZE" -gt "5000" && test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms1G -Xmx3G],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) - fi - if test "$MEMORY_SIZE" -gt "3800" && test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms1G -Xmx2500M],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) + else + MS_VALUE=256 + if test "$MX_VALUE" -gt "1500"; then + MX_VALUE=1500 fi fi - if test "$MEMORY_SIZE" -gt "2500" && test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms1000M -Xmx1500M],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) - fi - if test "$MEMORY_SIZE" -gt "1000" && test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms400M -Xmx1100M],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) - fi - if test "$JVM_ARG_OK" = false; then - ADD_JVM_ARG_IF_OK([-Xms256M -Xmx512M],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) + if test "$MX_VALUE" -lt "512"; then + MX_VALUE=512 fi + ADD_JVM_ARG_IF_OK([-Xms${MS_VALUE}M -Xmx${MX_VALUE}M],SJAVAC_SERVER_JAVA,[$SJAVAC_SERVER_JAVA]) - AC_MSG_CHECKING([whether to use sjavac]) AC_ARG_ENABLE([sjavac], [AS_HELP_STRING([--enable-sjavac], [use sjavac to do fast incremental compiles @<:@disabled@:>@])], [ENABLE_SJAVAC="${enableval}"], [ENABLE_SJAVAC='no']) + if test "x$JVM_ARG_OK" = "xfalse"; then + AC_MSG_WARN([Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling sjavac]) + ENABLE_SJAVAC=no; + fi + AC_MSG_CHECKING([whether to use sjavac]) AC_MSG_RESULT([$ENABLE_SJAVAC]) AC_SUBST(ENABLE_SJAVAC) diff --git a/common/autoconf/configure.ac b/common/autoconf/configure.ac index ec0d7490d59..481d328a1c4 100644 --- a/common/autoconf/configure.ac +++ b/common/autoconf/configure.ac @@ -54,6 +54,7 @@ m4_include([toolchain_windows.m4]) AC_DEFUN_ONCE([CUSTOM_EARLY_HOOK]) AC_DEFUN_ONCE([CUSTOM_LATE_HOOK]) +AC_DEFUN_ONCE([CUSTOM_SUMMARY_AND_WARNINGS_HOOK]) # This line needs to be here, verbatim, after all includes and the dummy hook # definitions. It is replaced with custom functionality when building @@ -142,7 +143,6 @@ JDKOPT_SETUP_JDK_VERSION_NUMBERS ############################################################################### BOOTJDK_SETUP_BOOT_JDK -BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS ############################################################################### # @@ -233,6 +233,9 @@ BPERF_SETUP_BUILD_CORES BPERF_SETUP_BUILD_MEMORY BPERF_SETUP_BUILD_JOBS +# Setup arguments for the boot jdk (after cores and memory have been setup) +BOOTJDK_SETUP_BOOT_JDK_ARGUMENTS + # Setup smart javac (after cores and memory have been setup) BPERF_SETUP_SMART_JAVAC @@ -271,3 +274,4 @@ $CHMOD +x $OUTPUT_ROOT/compare.sh # Finally output some useful information to the user HELP_PRINT_SUMMARY_AND_WARNINGS +CUSTOM_SUMMARY_AND_WARNINGS_HOOK diff --git a/common/autoconf/flags.m4 b/common/autoconf/flags.m4 index 6f69f0c53a2..7a62d93ea7f 100644 --- a/common/autoconf/flags.m4 +++ b/common/autoconf/flags.m4 @@ -342,17 +342,15 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_FOR_OPTIMIZATION], # no adjustment ;; fastdebug ) - # Add compile time bounds checks. - CFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1" - CXXFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1" + # no adjustment ;; slowdebug ) - # Add runtime bounds checks and symbol info. - CFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1" - CXXFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1" + # Add runtime stack smashing and undefined behavior checks + CFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1" + CXXFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1" if test "x$HAS_CFLAG_DETECT_UNDEFINED_BEHAVIOR" = "xtrue"; then CFLAGS_DEBUG_OPTIONS="$CFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIOR_FLAG" - CXXFLAGS_DEBUG_OPTIONS="$CXXFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIOR_FLAG" + CXXFLAGS_DEBUG_OPTIONS="$CXXFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIsOR_FLAG" fi ;; esac @@ -900,7 +898,7 @@ AC_DEFUN_ONCE([FLAGS_SETUP_COMPILER_FLAGS_MISC], case "${TOOLCHAIN_TYPE}" in microsoft) - CFLAGS_WARNINGS_ARE_ERRORS="/WX" + CFLAGS_WARNINGS_ARE_ERRORS="-WX" ;; solstudio) CFLAGS_WARNINGS_ARE_ERRORS="-errtags -errwarn=%all" diff --git a/common/autoconf/generated-configure.sh b/common/autoconf/generated-configure.sh index 5b044dc241d..8ceccb58d54 100644 --- a/common/autoconf/generated-configure.sh +++ b/common/autoconf/generated-configure.sh @@ -634,6 +634,10 @@ USE_PRECOMPILED_HEADER SJAVAC_SERVER_DIR ENABLE_SJAVAC SJAVAC_SERVER_JAVA +JAVA_TOOL_FLAGS_SMALL +JAVA_FLAGS_SMALL +JAVA_FLAGS_BIG +JAVA_FLAGS JOBS MEMORY_SIZE NUM_CORES @@ -749,6 +753,7 @@ MCS GNM NM STRIP +MSBUILD DUMPBIN RC MT @@ -805,10 +810,6 @@ JAXWS_TOPDIR JAXP_TOPDIR CORBA_TOPDIR LANGTOOLS_TOPDIR -JAVA_TOOL_FLAGS_SMALL -JAVA_FLAGS_SMALL -JAVA_FLAGS_BIG -JAVA_FLAGS JAVAC_FLAGS BOOT_JDK_SOURCETARGET JARSIGNER @@ -920,12 +921,14 @@ OPENJDK_TARGET_CPU_ENDIAN OPENJDK_TARGET_CPU_BITS OPENJDK_TARGET_CPU_ARCH OPENJDK_TARGET_CPU +OPENJDK_TARGET_OS_ENV OPENJDK_TARGET_OS_API OPENJDK_TARGET_OS OPENJDK_BUILD_CPU_ENDIAN OPENJDK_BUILD_CPU_BITS OPENJDK_BUILD_CPU_ARCH OPENJDK_BUILD_CPU +OPENJDK_BUILD_OS_ENV OPENJDK_BUILD_OS_API OPENJDK_BUILD_OS OPENJDK_BUILD_AUTOCONF_NAME @@ -942,6 +945,7 @@ build_os build_vendor build_cpu build +CPIO SETFILE DF READLINK @@ -980,7 +984,6 @@ DIRNAME DIFF DATE CUT -CPIO CP COMM CMP @@ -1062,7 +1065,6 @@ with_update_version with_user_release_suffix with_build_number with_boot_jdk -with_boot_jdk_jvmargs with_add_source_root with_override_source_root with_adds_and_overrides @@ -1087,6 +1089,7 @@ with_cups_include with_freetype with_freetype_include with_freetype_lib +with_freetype_src enable_freetype_bundling with_alsa with_alsa_include @@ -1104,6 +1107,7 @@ with_dxsdk_include with_num_cores with_memory_size with_jobs +with_boot_jdk_jvmargs with_sjavac_server_java enable_sjavac enable_precompiled_headers @@ -1120,7 +1124,6 @@ CHMOD CMP COMM CP -CPIO CUT DATE DIFF @@ -1159,6 +1162,7 @@ CYGPATH READLINK DF SETFILE +CPIO UNZIP ZIP LDD @@ -1902,10 +1906,6 @@ Optional Packages: number is not set.[username_builddateb00] --with-build-number Set build number value for build [b00] --with-boot-jdk path to Boot JDK (used to bootstrap build) [probed] - --with-boot-jdk-jvmargs specify JVM arguments to be passed to all java - invocations of boot JDK, overriding the default - values, e.g --with-boot-jdk-jvmargs="-Xmx8G - -enableassertions" --with-add-source-root for each and every source directory, look in this additional source root for the same directory; if it exists and have files in it, include it in the build @@ -1944,6 +1944,9 @@ Optional Packages: headers under PATH/include) --with-freetype-include specify directory for the freetype include files --with-freetype-lib specify directory for the freetype library + --with-freetype-src specify directory with freetype sources to + automatically build the library (experimental, + Windows-only) --with-alsa specify prefix directory for the alsa package (expecting the libraries under PATH/lib and the headers under PATH/include) @@ -1977,6 +1980,10 @@ Optional Packages: --with-memory-size=1024 [probed] --with-jobs number of parallel jobs to let make run [calculated based on cores and memory] + --with-boot-jdk-jvmargs specify JVM arguments to be passed to all java + invocations of boot JDK, overriding the default + values, e.g --with-boot-jdk-jvmargs="-Xmx8G + -enableassertions" --with-sjavac-server-java use this java binary for running the sjavac background server [Boot JDK java] @@ -1990,7 +1997,6 @@ Some influential environment variables: CMP Override default value for CMP COMM Override default value for COMM CP Override default value for CP - CPIO Override default value for CPIO CUT Override default value for CUT DATE Override default value for DATE DIFF Override default value for DIFF @@ -2029,6 +2035,7 @@ Some influential environment variables: READLINK Override default value for READLINK DF Override default value for DF SETFILE Override default value for SETFILE + CPIO Override default value for CPIO UNZIP Override default value for UNZIP ZIP Override default value for ZIP LDD Override default value for LDD @@ -3880,20 +3887,18 @@ cygwin_help() { HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'." ;; freetype) - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - HELP_MSG="To install freetype, run: -wget \"http://gnuwin32.sourceforge.net/downlinks/freetype.php\" -O /tmp/freetype-setup.exe -chmod +x /tmp/freetype-setup.exe -/tmp/freetype-setup.exe -Follow GUI prompts, and install to default directory \"C:\Program Files (x86)\GnuWin32\". -After installation, locate lib/libfreetype.dll.a and make a copy with the name freetype.dll." - else - HELP_MSG="You need to build a 64-bit version of freetype. -This is not readily available. -You can find source code and build instructions on -http://www.freetype.org/ -If you put the resulting build in \"C:\Program Files\GnuWin32\", it will be found automatically." - fi + HELP_MSG=" +The freetype library can now be build during the configure process. +Download the freetype sources and unpack them into an arbitrary directory: + +wget http://download.savannah.gnu.org/releases/freetype/freetype-2.5.3.tar.gz +tar -xzf freetype-2.5.3.tar.gz + +Then run configure with '--with-freetype-src='. This will +automatically build the freetype library into '/lib64' for 64-bit +builds or into '/lib32' for 32-bit builds. +Afterwards you can always use '--with-freetype-include=/include' +and '--with-freetype-lib=/lib32|64' for other builds." ;; esac } @@ -4058,6 +4063,8 @@ pkgadd_help() { + + # # Copyright (c) 2011, 2012, Oracle and/or its affiliates. All rights reserved. @@ -4313,13 +4320,14 @@ TOOLCHAIN_DESCRIPTION_xlc="IBM XL C/C++" + # This line needs to be here, verbatim, after all includes and the dummy hook # definitions. It is replaced with custom functionality when building # custom sources. #CUSTOM_AUTOCONF_INCLUDE # Do not change or remove the following line, it is needed for consistency checks: -DATE_WHEN_GENERATED=1407143049 +DATE_WHEN_GENERATED=1410377275 ############################################################################### # @@ -5721,199 +5729,6 @@ $as_echo "$tool_specified" >&6; } - # Publish this variable in the help. - - - if test "x$CPIO" = x; then - # The variable is not set by user, try to locate tool using the code snippet - for ac_prog in cpio -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_CPIO+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $CPIO in - [\\/]* | ?:[\\/]*) - ac_cv_path_CPIO="$CPIO" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_CPIO="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -CPIO=$ac_cv_path_CPIO -if test -n "$CPIO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 -$as_echo "$CPIO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CPIO" && break -done - - else - # The variable is set, but is it from the command line or the environment? - - # Try to remove the string !CPIO! from our list. - try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!CPIO!/} - if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then - # If it failed, the variable was not from the command line. Ignore it, - # but warn the user (except for BASH, which is always set by the calling BASH). - if test "xCPIO" != xBASH; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of CPIO from the environment. Use command line variables instead." >&5 -$as_echo "$as_me: WARNING: Ignoring value of CPIO from the environment. Use command line variables instead." >&2;} - fi - # Try to locate tool using the code snippet - for ac_prog in cpio -do - # Extract the first word of "$ac_prog", so it can be a program name with args. -set dummy $ac_prog; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_CPIO+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $CPIO in - [\\/]* | ?:[\\/]*) - ac_cv_path_CPIO="$CPIO" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_CPIO="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -CPIO=$ac_cv_path_CPIO -if test -n "$CPIO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 -$as_echo "$CPIO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - test -n "$CPIO" && break -done - - else - # If it succeeded, then it was overridden by the user. We will use it - # for the tool. - - # First remove it from the list of overridden variables, so we can test - # for unknown variables in the end. - CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" - - # Check if the provided tool contains a complete path. - tool_specified="$CPIO" - tool_basename="${tool_specified##*/}" - if test "x$tool_basename" = "x$tool_specified"; then - # A command without a complete path is provided, search $PATH. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool CPIO=$tool_basename" >&5 -$as_echo "$as_me: Will search for user supplied tool CPIO=$tool_basename" >&6;} - # Extract the first word of "$tool_basename", so it can be a program name with args. -set dummy $tool_basename; ac_word=$2 -{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if ${ac_cv_path_CPIO+:} false; then : - $as_echo_n "(cached) " >&6 -else - case $CPIO in - [\\/]* | ?:[\\/]*) - ac_cv_path_CPIO="$CPIO" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then - ac_cv_path_CPIO="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done - done -IFS=$as_save_IFS - - ;; -esac -fi -CPIO=$ac_cv_path_CPIO -if test -n "$CPIO"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 -$as_echo "$CPIO" >&6; } -else - { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 -$as_echo "no" >&6; } -fi - - - if test "x$CPIO" = x; then - as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 - fi - else - # Otherwise we believe it is a complete path. Use it as it is. - { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool CPIO=$tool_specified" >&5 -$as_echo "$as_me: Will use user supplied tool CPIO=$tool_specified" >&6;} - { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CPIO" >&5 -$as_echo_n "checking for CPIO... " >&6; } - if test ! -x "$tool_specified"; then - { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 -$as_echo "not found" >&6; } - as_fn_error $? "User supplied tool CPIO=$tool_specified does not exist or is not executable" "$LINENO" 5 - fi - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 -$as_echo "$tool_specified" >&6; } - fi - fi - fi - - - - if test "x$CPIO" = x; then - as_fn_error $? "Could not find required tool for CPIO" "$LINENO" 5 - fi - - - - - # Publish this variable in the help. @@ -13386,6 +13201,192 @@ $as_echo "$tool_specified" >&6; } + # Publish this variable in the help. + + + if test "x$CPIO" = x; then + # The variable is not set by user, try to locate tool using the code snippet + for ac_prog in cpio bsdcpio +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CPIO+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CPIO in + [\\/]* | ?:[\\/]*) + ac_cv_path_CPIO="$CPIO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CPIO="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +CPIO=$ac_cv_path_CPIO +if test -n "$CPIO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 +$as_echo "$CPIO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CPIO" && break +done + + else + # The variable is set, but is it from the command line or the environment? + + # Try to remove the string !CPIO! from our list. + try_remove_var=${CONFIGURE_OVERRIDDEN_VARIABLES//!CPIO!/} + if test "x$try_remove_var" = "x$CONFIGURE_OVERRIDDEN_VARIABLES"; then + # If it failed, the variable was not from the command line. Ignore it, + # but warn the user (except for BASH, which is always set by the calling BASH). + if test "xCPIO" != xBASH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Ignoring value of CPIO from the environment. Use command line variables instead." >&5 +$as_echo "$as_me: WARNING: Ignoring value of CPIO from the environment. Use command line variables instead." >&2;} + fi + # Try to locate tool using the code snippet + for ac_prog in cpio bsdcpio +do + # Extract the first word of "$ac_prog", so it can be a program name with args. +set dummy $ac_prog; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CPIO+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CPIO in + [\\/]* | ?:[\\/]*) + ac_cv_path_CPIO="$CPIO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CPIO="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +CPIO=$ac_cv_path_CPIO +if test -n "$CPIO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 +$as_echo "$CPIO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + test -n "$CPIO" && break +done + + else + # If it succeeded, then it was overridden by the user. We will use it + # for the tool. + + # First remove it from the list of overridden variables, so we can test + # for unknown variables in the end. + CONFIGURE_OVERRIDDEN_VARIABLES="$try_remove_var" + + # Check if the provided tool contains a complete path. + tool_specified="$CPIO" + tool_basename="${tool_specified##*/}" + if test "x$tool_basename" = "x$tool_specified"; then + # A command without a complete path is provided, search $PATH. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will search for user supplied tool CPIO=$tool_basename" >&5 +$as_echo "$as_me: Will search for user supplied tool CPIO=$tool_basename" >&6;} + # Extract the first word of "$tool_basename", so it can be a program name with args. +set dummy $tool_basename; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_path_CPIO+:} false; then : + $as_echo_n "(cached) " >&6 +else + case $CPIO in + [\\/]* | ?:[\\/]*) + ac_cv_path_CPIO="$CPIO" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_path_CPIO="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + + ;; +esac +fi +CPIO=$ac_cv_path_CPIO +if test -n "$CPIO"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPIO" >&5 +$as_echo "$CPIO" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + + if test "x$CPIO" = x; then + as_fn_error $? "User supplied tool $tool_basename could not be found" "$LINENO" 5 + fi + else + # Otherwise we believe it is a complete path. Use it as it is. + { $as_echo "$as_me:${as_lineno-$LINENO}: Will use user supplied tool CPIO=$tool_specified" >&5 +$as_echo "$as_me: Will use user supplied tool CPIO=$tool_specified" >&6;} + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for CPIO" >&5 +$as_echo_n "checking for CPIO... " >&6; } + if test ! -x "$tool_specified"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5 +$as_echo "not found" >&6; } + as_fn_error $? "User supplied tool CPIO=$tool_specified does not exist or is not executable" "$LINENO" 5 + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $tool_specified" >&5 +$as_echo "$tool_specified" >&6; } + fi + fi + fi + + + + # Now we can determine OpenJDK build and target platforms. This is required to # have early on. # Make sure we can run config.sub. @@ -13644,6 +13645,7 @@ test -n "$target_alias" && + { $as_echo "$as_me:${as_lineno-$LINENO}: checking openjdk-build os-cpu" >&5 $as_echo_n "checking openjdk-build os-cpu... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENJDK_BUILD_OS-$OPENJDK_BUILD_CPU" >&5 @@ -13775,6 +13777,7 @@ $as_echo "$OPENJDK_BUILD_OS-$OPENJDK_BUILD_CPU" >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: checking openjdk-target os-cpu" >&5 $as_echo_n "checking openjdk-target os-cpu... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $OPENJDK_TARGET_OS-$OPENJDK_TARGET_CPU" >&5 @@ -15611,6 +15614,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -15967,6 +15987,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -16320,6 +16357,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -16678,6 +16732,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -17030,6 +17101,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -17202,7 +17290,12 @@ $as_echo_n "checking if find supports -delete... " >&6; } if test -f $DELETEDIR/TestIfFindSupportsDelete; then # No, it does not. rm $DELETEDIR/TestIfFindSupportsDelete - FIND_DELETE="-exec rm \{\} \+" + if test "x$OPENJDK_TARGET_OS" = "xaix"; then + # AIX 'find' is buggy if called with '-exec {} \+' and an empty file list + FIND_DELETE="-print | xargs rm" + else + FIND_DELETE="-exec rm \{\} \+" + fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 $as_echo "no" >&6; } else @@ -26233,197 +26326,6 @@ $as_echo "$tool_specified" >&6; } - ############################################################################## - # - # Specify jvm options for anything that is run with the Boot JDK. - # Not all JVM:s accept the same arguments on the command line. - # - -# Check whether --with-boot-jdk-jvmargs was given. -if test "${with_boot_jdk_jvmargs+set}" = set; then : - withval=$with_boot_jdk_jvmargs; -fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command " >&5 -$as_echo_n "checking flags for boot jdk java command ... " >&6; } - - # Disable special log output when a debug build is used as Boot JDK... - - $ECHO "Check if jvm arg is ok: -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput" >&5 - $ECHO "Command: $JAVA -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput -version" >&5 - OUTPUT=`$JAVA -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - boot_jdk_jvmargs="$boot_jdk_jvmargs -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - # Apply user provided options. - - $ECHO "Check if jvm arg is ok: $with_boot_jdk_jvmargs" >&5 - $ECHO "Command: $JAVA $with_boot_jdk_jvmargs -version" >&5 - OUTPUT=`$JAVA $with_boot_jdk_jvmargs -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - boot_jdk_jvmargs="$boot_jdk_jvmargs $with_boot_jdk_jvmargs" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs" >&5 -$as_echo "$boot_jdk_jvmargs" >&6; } - - # For now, general JAVA_FLAGS are the same as the boot jdk jvmargs - JAVA_FLAGS=$boot_jdk_jvmargs - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command for big workloads" >&5 -$as_echo_n "checking flags for boot jdk java command for big workloads... " >&6; } - - # Starting amount of heap memory. - - $ECHO "Check if jvm arg is ok: -Xms64M" >&5 - $ECHO "Command: $JAVA -Xms64M -version" >&5 - OUTPUT=`$JAVA -Xms64M -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -Xms64M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - # Maximum amount of heap memory. - # Maximum stack size. - if test "x$BUILD_NUM_BITS" = x32; then - JVM_MAX_HEAP=1100M - STACK_SIZE=768 - else - # Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit - # pointers are used. Apparently, we need to increase the heap and stack - # space for the jvm. More specifically, when running javac to build huge - # jdk batch - JVM_MAX_HEAP=1600M - STACK_SIZE=1536 - fi - - $ECHO "Check if jvm arg is ok: -Xmx$JVM_MAX_HEAP" >&5 - $ECHO "Command: $JAVA -Xmx$JVM_MAX_HEAP -version" >&5 - OUTPUT=`$JAVA -Xmx$JVM_MAX_HEAP -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -Xmx$JVM_MAX_HEAP" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - $ECHO "Check if jvm arg is ok: -XX:ThreadStackSize=$STACK_SIZE" >&5 - $ECHO "Command: $JAVA -XX:ThreadStackSize=$STACK_SIZE -version" >&5 - OUTPUT=`$JAVA -XX:ThreadStackSize=$STACK_SIZE -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -XX:ThreadStackSize=$STACK_SIZE" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_big" >&5 -$as_echo "$boot_jdk_jvmargs_big" >&6; } - - JAVA_FLAGS_BIG=$boot_jdk_jvmargs_big - - - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command for small workloads" >&5 -$as_echo_n "checking flags for boot jdk java command for small workloads... " >&6; } - - # Use serial gc for small short lived tools if possible - - $ECHO "Check if jvm arg is ok: -XX:+UseSerialGC" >&5 - $ECHO "Command: $JAVA -XX:+UseSerialGC -version" >&5 - OUTPUT=`$JAVA -XX:+UseSerialGC -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -XX:+UseSerialGC" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - $ECHO "Check if jvm arg is ok: -Xms32M" >&5 - $ECHO "Command: $JAVA -Xms32M -version" >&5 - OUTPUT=`$JAVA -Xms32M -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -Xms32M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - $ECHO "Check if jvm arg is ok: -Xmx512M" >&5 - $ECHO "Command: $JAVA -Xmx512M -version" >&5 - OUTPUT=`$JAVA -Xmx512M -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -Xmx512M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - - { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_small" >&5 -$as_echo "$boot_jdk_jvmargs_small" >&6; } - - JAVA_FLAGS_SMALL=$boot_jdk_jvmargs_small - - - JAVA_TOOL_FLAGS_SMALL="" - for f in $JAVA_FLAGS_SMALL; do - JAVA_TOOL_FLAGS_SMALL="$JAVA_TOOL_FLAGS_SMALL -J$f" - done - - - ############################################################################### # # Configure the sources to use. We can add or override individual directories. @@ -26985,6 +26887,10 @@ $as_echo "no" >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;} VS_ENV_CMD="$VS100BASE/$VCVARSFILE" + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013 + # TODO: improve detection for other versions of VS + PLATFORM_TOOLSET="v100" else { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;} @@ -27026,6 +26932,10 @@ $as_echo "$as_me: Please point to the VC/bin directory within the Visual Studio { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;} VS_ENV_CMD="$VS100BASE/$VCVARSFILE" + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013 + # TODO: improve detection for other versions of VS + PLATFORM_TOOLSET="v100" else { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;} @@ -27056,6 +26966,10 @@ $as_echo "$as_me: Warning: $VCVARSFILE is missing, this is probably Visual Studi { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;} VS_ENV_CMD="$VS100BASE/$VCVARSFILE" + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013 + # TODO: improve detection for other versions of VS + PLATFORM_TOOLSET="v100" else { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;} @@ -27085,6 +26999,10 @@ $as_echo "$as_me: Warning: $VCVARSFILE is missing, this is probably Visual Studi { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;} VS_ENV_CMD="$VS100BASE/$VCVARSFILE" + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013 + # TODO: improve detection for other versions of VS + PLATFORM_TOOLSET="v100" else { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;} @@ -27113,6 +27031,10 @@ $as_echo "$as_me: Warning: $VCVARSFILE is missing, this is probably Visual Studi { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;} VS_ENV_CMD="$VS100BASE/$VCVARSFILE" + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013 + # TODO: improve detection for other versions of VS + PLATFORM_TOOLSET="v100" else { $as_echo "$as_me:${as_lineno-$LINENO}: Found Visual Studio installation at $VS100BASE using $METHOD" >&5 $as_echo "$as_me: Found Visual Studio installation at $VS100BASE using $METHOD" >&6;} @@ -27155,6 +27077,10 @@ $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" else VS_ENV_ARGS="/x64" fi + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK + # TODO: improve detection for other versions of SDK + PLATFORM_TOOLSET="Windows7.1SDK" else { $as_echo "$as_me:${as_lineno-$LINENO}: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&5 $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&6;} @@ -27197,6 +27123,10 @@ $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" else VS_ENV_ARGS="/x64" fi + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK + # TODO: improve detection for other versions of SDK + PLATFORM_TOOLSET="Windows7.1SDK" else { $as_echo "$as_me:${as_lineno-$LINENO}: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&5 $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&6;} @@ -27239,6 +27169,10 @@ $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" else VS_ENV_ARGS="/x64" fi + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK + # TODO: improve detection for other versions of SDK + PLATFORM_TOOLSET="Windows7.1SDK" else { $as_echo "$as_me:${as_lineno-$LINENO}: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&5 $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&6;} @@ -27280,6 +27214,10 @@ $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" else VS_ENV_ARGS="/x64" fi + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK + # TODO: improve detection for other versions of SDK + PLATFORM_TOOLSET="Windows7.1SDK" else { $as_echo "$as_me:${as_lineno-$LINENO}: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&5 $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&6;} @@ -27320,6 +27258,10 @@ $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" else VS_ENV_ARGS="/x64" fi + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK + # TODO: improve detection for other versions of SDK + PLATFORM_TOOLSET="Windows7.1SDK" else { $as_echo "$as_me:${as_lineno-$LINENO}: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&5 $as_echo "$as_me: Found Windows SDK installation at $WIN_SDK_BASE using $METHOD" >&6;} @@ -27493,6 +27435,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -28136,6 +28095,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -28576,6 +28552,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -29842,6 +29835,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -30282,6 +30292,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -31127,6 +31154,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -31525,6 +31569,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -31852,6 +31913,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -32330,6 +32408,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -32941,6 +33036,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -33460,6 +33572,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -33911,6 +34040,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -34235,6 +34381,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -34555,6 +34718,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -34857,6 +35037,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -34961,6 +35158,50 @@ $as_echo "$as_me: This might be caused by spaces in the path, which is not allow $as_echo "$as_me: Rewriting DUMPBIN to \"$new_complete\"" >&6;} fi + # We need to check for 'msbuild.exe' because at the place where we expect to + # find 'msbuild.exe' there's also a directory called 'msbuild' and configure + # won't find the 'msbuild.exe' executable in that case (and the + # 'ac_executable_extensions' is unusable due to performance reasons). + # Notice that we intentionally don't fix up the path to MSBUILD because we + # will call it in a DOS shell during freetype detection on Windows (see + # 'LIB_SETUP_FREETYPE' in "libraries.m4" + # Extract the first word of "msbuild.exe", so it can be a program name with args. +set dummy msbuild.exe; ac_word=$2 +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if ${ac_cv_prog_MSBUILD+:} false; then : + $as_echo_n "(cached) " >&6 +else + if test -n "$MSBUILD"; then + ac_cv_prog_MSBUILD="$MSBUILD" # Let the user override the test. +else +as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then + ac_cv_prog_MSBUILD="msbuild.exe" + $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done + done +IFS=$as_save_IFS + +fi +fi +MSBUILD=$ac_cv_prog_MSBUILD +if test -n "$MSBUILD"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $MSBUILD" >&5 +$as_echo "$MSBUILD" >&6; } +else + { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5 +$as_echo "no" >&6; } +fi + + fi if test "x$OPENJDK_TARGET_OS" = xsolaris; then @@ -35311,6 +35552,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -35762,6 +36020,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -36213,6 +36488,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -36665,6 +36957,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -37228,6 +37537,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -37789,6 +38115,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -38359,6 +38702,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -38926,6 +39286,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -39402,6 +39779,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -39853,6 +40247,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -40304,6 +40715,23 @@ $as_echo "$as_me: Neither \"$new_path\" nor \"$new_path.exe/cmd\" can be found" new_path=`$WHICH "$new_path" 2> /dev/null` + # bat and cmd files are not always considered executable in MSYS causing which + # to not find them + if test "x$new_path" = x \ + && test "x`$ECHO \"$path\" | $GREP -i -e \"\\.bat$\" -e \"\\.cmd$\"`" != x \ + && test "x`$LS \"$path\" 2>/dev/null`" != x; then + new_path="$path" + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + fi if test "x$new_path" = x; then # It's still not found. Now this is an unrecoverable error. @@ -41991,17 +42419,15 @@ $as_echo "$ac_cv_c_bigendian" >&6; } # no adjustment ;; fastdebug ) - # Add compile time bounds checks. - CFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1" - CXXFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=1" + # no adjustment ;; slowdebug ) - # Add runtime bounds checks and symbol info. - CFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1" - CXXFLAGS_DEBUG_OPTIONS="-U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fstack-protector-all --param ssp-buffer-size=1" + # Add runtime stack smashing and undefined behavior checks + CFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1" + CXXFLAGS_DEBUG_OPTIONS="-fstack-protector-all --param ssp-buffer-size=1" if test "x$HAS_CFLAG_DETECT_UNDEFINED_BEHAVIOR" = "xtrue"; then CFLAGS_DEBUG_OPTIONS="$CFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIOR_FLAG" - CXXFLAGS_DEBUG_OPTIONS="$CXXFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIOR_FLAG" + CXXFLAGS_DEBUG_OPTIONS="$CXXFLAGS_DEBUG_OPTIONS $CFLAG_DETECT_UNDEFINED_BEHAVIsOR_FLAG" fi ;; esac @@ -42629,7 +43055,7 @@ $as_echo "$supports" >&6; } case "${TOOLCHAIN_TYPE}" in microsoft) - CFLAGS_WARNINGS_ARE_ERRORS="/WX" + CFLAGS_WARNINGS_ARE_ERRORS="-WX" ;; solstudio) CFLAGS_WARNINGS_ARE_ERRORS="-errtags -errwarn=%all" @@ -43982,6 +44408,12 @@ if test "${with_freetype_lib+set}" = set; then : withval=$with_freetype_lib; fi + +# Check whether --with-freetype-src was given. +if test "${with_freetype_src+set}" = set; then : + withval=$with_freetype_src; +fi + # Check whether --enable-freetype-bundling was given. if test "${enable_freetype_bundling+set}" = set; then : enableval=$enable_freetype_bundling; @@ -43993,7 +44425,7 @@ fi FREETYPE_BUNDLE_LIB_PATH= if test "x$FREETYPE_NOT_NEEDED" = xyes; then - if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x; then + if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x || test "x$with_freetype_src" != x; then { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: freetype not used, so --with-freetype is ignored" >&5 $as_echo "$as_me: WARNING: freetype not used, so --with-freetype is ignored" >&2;} fi @@ -44006,6 +44438,429 @@ $as_echo "$as_me: WARNING: freetype not used, so --enable-freetype-bundling is i BUNDLE_FREETYPE="$enable_freetype_bundling" + if test "x$with_freetype_src" != x; then + if test "x$OPENJDK_TARGET_OS" = xwindows; then + # Try to build freetype if --with-freetype-src was given on Windows + + FREETYPE_SRC_PATH="$with_freetype_src" + BUILD_FREETYPE=yes + + # Check if the freetype sources are acessible.. + if ! test -d $FREETYPE_SRC_PATH; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-freetype-src specified, but can't find path \"$FREETYPE_SRC_PATH\" - ignoring --with-freetype-src" >&5 +$as_echo "$as_me: WARNING: --with-freetype-src specified, but can't find path \"$FREETYPE_SRC_PATH\" - ignoring --with-freetype-src" >&2;} + BUILD_FREETYPE=no + fi + # ..and contain a vc2010 project file + vcxproj_path="$FREETYPE_SRC_PATH/builds/windows/vc2010/freetype.vcxproj" + if test "x$BUILD_FREETYPE" = xyes && ! test -s $vcxproj_path; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find project file $vcxproj_path (you may try a newer freetype version) - ignoring --with-freetype-src" >&5 +$as_echo "$as_me: WARNING: Can't find project file $vcxproj_path (you may try a newer freetype version) - ignoring --with-freetype-src" >&2;} + BUILD_FREETYPE=no + fi + # Now check if configure found a version of 'msbuild.exe' + if test "x$BUILD_FREETYPE" = xyes && test "x$MSBUILD" == x ; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Can't find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src" >&5 +$as_echo "$as_me: WARNING: Can't find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src" >&2;} + BUILD_FREETYPE=no + fi + + # Ready to go.. + if test "x$BUILD_FREETYPE" = xyes; then + + # msbuild requires trailing slashes for output directories + freetype_lib_path="$FREETYPE_SRC_PATH/lib$OPENJDK_TARGET_CPU_BITS/" + freetype_lib_path_unix="$freetype_lib_path" + freetype_obj_path="$FREETYPE_SRC_PATH/obj$OPENJDK_TARGET_CPU_BITS/" + + unix_path="$vcxproj_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + windows_path=`$CYGPATH -m "$unix_path"` + vcxproj_path="$windows_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + windows_path=`cmd //c echo $unix_path` + vcxproj_path="$windows_path" + fi + + + unix_path="$freetype_lib_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + windows_path=`$CYGPATH -m "$unix_path"` + freetype_lib_path="$windows_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + windows_path=`cmd //c echo $unix_path` + freetype_lib_path="$windows_path" + fi + + + unix_path="$freetype_obj_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + windows_path=`$CYGPATH -m "$unix_path"` + freetype_obj_path="$windows_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + windows_path=`cmd //c echo $unix_path` + freetype_obj_path="$windows_path" + fi + + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + freetype_platform=x64 + else + freetype_platform=win32 + fi + + # The original freetype project file is for VS 2010 (i.e. 'v100'), + # so we have to adapt the toolset if building with any other toolsed (i.e. SDK). + # Currently 'PLATFORM_TOOLSET' is set in 'TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT'/ + # 'TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT' in toolchain_windows.m4 + { $as_echo "$as_me:${as_lineno-$LINENO}: Trying to compile freetype sources with PlatformToolset=$PLATFORM_TOOLSET to $freetype_lib_path_unix ..." >&5 +$as_echo "$as_me: Trying to compile freetype sources with PlatformToolset=$PLATFORM_TOOLSET to $freetype_lib_path_unix ..." >&6;} + + # First we try to build the freetype.dll + $ECHO -e "@echo off\n"\ + "$MSBUILD $vcxproj_path "\ + "/p:PlatformToolset=$PLATFORM_TOOLSET "\ + "/p:Configuration=\"Release Multithreaded\" "\ + "/p:Platform=$freetype_platform "\ + "/p:ConfigurationType=DynamicLibrary "\ + "/p:TargetName=freetype "\ + "/p:OutDir=\"$freetype_lib_path\" "\ + "/p:IntDir=\"$freetype_obj_path\" > freetype.log" > freetype.bat + cmd /c freetype.bat + + if test -s "$freetype_lib_path_unix/freetype.dll"; then + # If that succeeds we also build freetype.lib + $ECHO -e "@echo off\n"\ + "$MSBUILD $vcxproj_path "\ + "/p:PlatformToolset=$PLATFORM_TOOLSET "\ + "/p:Configuration=\"Release Multithreaded\" "\ + "/p:Platform=$freetype_platform "\ + "/p:ConfigurationType=StaticLibrary "\ + "/p:TargetName=freetype "\ + "/p:OutDir=\"$freetype_lib_path\" "\ + "/p:IntDir=\"$freetype_obj_path\" >> freetype.log" > freetype.bat + cmd /c freetype.bat + + if test -s "$freetype_lib_path_unix/freetype.lib"; then + # Once we build both, lib and dll, set freetype lib and include path appropriately + POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_SRC_PATH/include" + POTENTIAL_FREETYPE_LIB_PATH="$freetype_lib_path_unix" + { $as_echo "$as_me:${as_lineno-$LINENO}: Compiling freetype sources succeeded! (see freetype.log for build results)" >&5 +$as_echo "$as_me: Compiling freetype sources succeeded! (see freetype.log for build results)" >&6;} + else + BUILD_FREETYPE=no + fi + else + BUILD_FREETYPE=no + fi + fi + + if test "x$BUILD_FREETYPE" = xyes; then + # Okay, we built it. Check that it works. + + POTENTIAL_FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH" + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH" + METHOD="--with-freetype-src" + + # First check if the files exists. + if test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then + # We found an arbitrary include file. That's a good sign. + { $as_echo "$as_me:${as_lineno-$LINENO}: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&5 +$as_echo "$as_me: Found freetype include files at $POTENTIAL_FREETYPE_INCLUDE_PATH using $METHOD" >&6;} + FOUND_FREETYPE=yes + + FREETYPE_LIB_NAME="${LIBRARY_PREFIX}freetype${SHARED_LIBRARY_SUFFIX}" + if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&5 +$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/$FREETYPE_LIB_NAME. Ignoring location." >&6;} + FOUND_FREETYPE=no + else + if test "x$OPENJDK_TARGET_OS" = xwindows; then + # On Windows, we will need both .lib and .dll file. + if ! test -s "$POTENTIAL_FREETYPE_LIB_PATH/freetype.lib"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&5 +$as_echo "$as_me: Could not find $POTENTIAL_FREETYPE_LIB_PATH/freetype.lib. Ignoring location." >&6;} + FOUND_FREETYPE=no + fi + elif test "x$OPENJDK_TARGET_OS" = xsolaris \ + && test -s "$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR/$FREETYPE_LIB_NAME"; then + # Found lib in isa dir, use that instead. + POTENTIAL_FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH$OPENJDK_TARGET_CPU_ISADIR" + fi + fi + fi + + if test "x$FOUND_FREETYPE" = xyes; then + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # Input might be given as Windows format, start by converting to + # unix format. + path="$POTENTIAL_FREETYPE_INCLUDE_PATH" + new_path=`$CYGPATH -u "$path"` + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file precense. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_INCLUDE_PATH" "$LINENO" 5 + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + + if test "x$path" != "x$new_path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;} + fi + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + path="$POTENTIAL_FREETYPE_INCLUDE_PATH" + has_colon=`$ECHO $path | $GREP ^.:` + new_path="$path" + if test "x$has_colon" = x; then + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $path` + fi + + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + if test "x$path" != "x$new_path"; then + POTENTIAL_FREETYPE_INCLUDE_PATH="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_INCLUDE_PATH to \"$new_path\"" >&6;} + fi + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + + else + # We're on a posix platform. Hooray! :) + path="$POTENTIAL_FREETYPE_INCLUDE_PATH" + has_space=`$ECHO "$path" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 + fi + + # Use eval to expand a potential ~ + eval path="$path" + if test ! -f "$path" && test ! -d "$path"; then + as_fn_error $? "The path of POTENTIAL_FREETYPE_INCLUDE_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 + fi + + POTENTIAL_FREETYPE_INCLUDE_PATH="`cd "$path"; $THEPWDCMD -L`" + fi + + + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + + # Input might be given as Windows format, start by converting to + # unix format. + path="$POTENTIAL_FREETYPE_LIB_PATH" + new_path=`$CYGPATH -u "$path"` + + # Cygwin tries to hide some aspects of the Windows file system, such that binaries are + # named .exe but called without that suffix. Therefore, "foo" and "foo.exe" are considered + # the same file, most of the time (as in "test -f"). But not when running cygpath -s, then + # "foo.exe" is OK but "foo" is an error. + # + # This test is therefore slightly more accurate than "test -f" to check for file precense. + # It is also a way to make sure we got the proper file name for the real test later on. + test_shortpath=`$CYGPATH -s -m "$new_path" 2> /dev/null` + if test "x$test_shortpath" = x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Cannot locate the the path of POTENTIAL_FREETYPE_LIB_PATH" "$LINENO" 5 + fi + + # Call helper function which possibly converts this using DOS-style short mode. + # If so, the updated path is stored in $new_path. + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-._/a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + shortmode_path=`$CYGPATH -s -m -a "$input_path"` + path_after_shortmode=`$CYGPATH -u "$shortmode_path"` + if test "x$path_after_shortmode" != "x$input_to_shortpath"; then + # Going to short mode and back again did indeed matter. Since short mode is + # case insensitive, let's make it lowercase to improve readability. + shortmode_path=`$ECHO "$shortmode_path" | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + # Now convert it back to Unix-stile (cygpath) + input_path=`$CYGPATH -u "$shortmode_path"` + new_path="$input_path" + fi + fi + + test_cygdrive_prefix=`$ECHO $input_path | $GREP ^/cygdrive/` + if test "x$test_cygdrive_prefix" = x; then + # As a simple fix, exclude /usr/bin since it's not a real path. + if test "x`$ECHO $new_path | $GREP ^/usr/bin/`" = x; then + # The path is in a Cygwin special directory (e.g. /home). We need this converted to + # a path prefixed by /cygdrive for fixpath to work. + new_path="$CYGWIN_ROOT_PATH$input_path" + fi + fi + + + if test "x$path" != "x$new_path"; then + POTENTIAL_FREETYPE_LIB_PATH="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;} + fi + + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + + path="$POTENTIAL_FREETYPE_LIB_PATH" + has_colon=`$ECHO $path | $GREP ^.:` + new_path="$path" + if test "x$has_colon" = x; then + # Not in mixed or Windows style, start by that. + new_path=`cmd //c echo $path` + fi + + + input_path="$new_path" + # Check if we need to convert this using DOS-style short mode. If the path + # contains just simple characters, use it. Otherwise (spaces, weird characters), + # take no chances and rewrite it. + # Note: m4 eats our [], so we need to use [ and ] instead. + has_forbidden_chars=`$ECHO "$input_path" | $GREP [^-_/:a-zA-Z0-9]` + if test "x$has_forbidden_chars" != x; then + # Now convert it to mixed DOS-style, short mode (no spaces, and / instead of \) + new_path=`cmd /c "for %A in (\"$input_path\") do @echo %~sA"|$TR \\\\\\\\ / | $TR 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' 'abcdefghijklmnopqrstuvwxyz'` + fi + + + windows_path="$new_path" + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then + unix_path=`$CYGPATH -u "$windows_path"` + new_path="$unix_path" + elif test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + unix_path=`$ECHO "$windows_path" | $SED -e 's,^\\(.\\):,/\\1,g' -e 's,\\\\,/,g'` + new_path="$unix_path" + fi + + if test "x$path" != "x$new_path"; then + POTENTIAL_FREETYPE_LIB_PATH="$new_path" + { $as_echo "$as_me:${as_lineno-$LINENO}: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&5 +$as_echo "$as_me: Rewriting POTENTIAL_FREETYPE_LIB_PATH to \"$new_path\"" >&6;} + fi + + # Save the first 10 bytes of this path to the storage, so fixpath can work. + all_fixpath_prefixes=("${all_fixpath_prefixes[@]}" "${new_path:0:10}") + + else + # We're on a posix platform. Hooray! :) + path="$POTENTIAL_FREETYPE_LIB_PATH" + has_space=`$ECHO "$path" | $GREP " "` + if test "x$has_space" != x; then + { $as_echo "$as_me:${as_lineno-$LINENO}: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&5 +$as_echo "$as_me: The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is invalid." >&6;} + as_fn_error $? "Spaces are not allowed in this path." "$LINENO" 5 + fi + + # Use eval to expand a potential ~ + eval path="$path" + if test ! -f "$path" && test ! -d "$path"; then + as_fn_error $? "The path of POTENTIAL_FREETYPE_LIB_PATH, which resolves as \"$path\", is not found." "$LINENO" 5 + fi + + POTENTIAL_FREETYPE_LIB_PATH="`cd "$path"; $THEPWDCMD -L`" + fi + + + FREETYPE_INCLUDE_PATH="$POTENTIAL_FREETYPE_INCLUDE_PATH" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype includes" >&5 +$as_echo_n "checking for freetype includes... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_INCLUDE_PATH" >&5 +$as_echo "$FREETYPE_INCLUDE_PATH" >&6; } + FREETYPE_LIB_PATH="$POTENTIAL_FREETYPE_LIB_PATH" + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for freetype libraries" >&5 +$as_echo_n "checking for freetype libraries... " >&6; } + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $FREETYPE_LIB_PATH" >&5 +$as_echo "$FREETYPE_LIB_PATH" >&6; } + fi + + if test "x$FOUND_FREETYPE" != xyes; then + as_fn_error $? "Can not use the built freetype at location given by --with-freetype-src" "$LINENO" 5 + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: User specified --with-freetype-src but building freetype failed. (see freetype.log for build results)" >&5 +$as_echo "$as_me: User specified --with-freetype-src but building freetype failed. (see freetype.log for build results)" >&6;} + as_fn_error $? "Consider building freetype manually and using --with-freetype instead." "$LINENO" 5 + fi + else + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: --with-freetype-src is currently only supported on Windows - ignoring" >&5 +$as_echo "$as_me: WARNING: --with-freetype-src is currently only supported on Windows - ignoring" >&2;} + fi + fi + if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x; then # User has specified settings @@ -48711,12 +49566,22 @@ $as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi else - CORRECT_MSVCR_ARCH=x86-64 + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -48767,12 +49632,22 @@ $as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi else - CORRECT_MSVCR_ARCH=x86-64 + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -48805,12 +49680,22 @@ $as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi else - CORRECT_MSVCR_ARCH=x86-64 + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -48853,12 +49738,22 @@ $as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi else - CORRECT_MSVCR_ARCH=x86-64 + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -48906,12 +49801,22 @@ $as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi else - CORRECT_MSVCR_ARCH=x86-64 + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -48955,12 +49860,22 @@ $as_echo "$as_me: Found msvcr100.dll at $POSSIBLE_MSVCR_DLL using $METHOD" >&6;} { $as_echo "$as_me:${as_lineno-$LINENO}: checking found msvcr100.dll architecture" >&5 $as_echo_n "checking found msvcr100.dll architecture... " >&6; } MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi else - CORRECT_MSVCR_ARCH=x86-64 + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then { $as_echo "$as_me:${as_lineno-$LINENO}: result: ok" >&5 $as_echo "ok" >&6; } MSVCR_DLL="$POSSIBLE_MSVCR_DLL" @@ -49300,8 +50215,8 @@ fi # Number of jobs was not specified, calculate. { $as_echo "$as_me:${as_lineno-$LINENO}: checking for appropriate number of jobs to run in parallel" >&5 $as_echo_n "checking for appropriate number of jobs to run in parallel... " >&6; } - # Approximate memory in GB, rounding up a bit. - memory_gb=`expr $MEMORY_SIZE / 1100` + # Approximate memory in GB. + memory_gb=`expr $MEMORY_SIZE / 1024` # Pick the lowest of memory in gb and number of cores. if test "$memory_gb" -lt "$NUM_CORES"; then JOBS="$memory_gb" @@ -49327,6 +50242,208 @@ $as_echo "$JOBS" >&6; } +# Setup arguments for the boot jdk (after cores and memory have been setup) + + ############################################################################## + # + # Specify jvm options for anything that is run with the Boot JDK. + # Not all JVM:s accept the same arguments on the command line. + # + +# Check whether --with-boot-jdk-jvmargs was given. +if test "${with_boot_jdk_jvmargs+set}" = set; then : + withval=$with_boot_jdk_jvmargs; +fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command " >&5 +$as_echo_n "checking flags for boot jdk java command ... " >&6; } + + # Disable special log output when a debug build is used as Boot JDK... + + $ECHO "Check if jvm arg is ok: -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput" >&5 + $ECHO "Command: $JAVA -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput -version" >&5 + OUTPUT=`$JAVA -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + boot_jdk_jvmargs="$boot_jdk_jvmargs -XX:-PrintVMOptions -XX:-UnlockDiagnosticVMOptions -XX:-LogVMOutput" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + # Apply user provided options. + + $ECHO "Check if jvm arg is ok: $with_boot_jdk_jvmargs" >&5 + $ECHO "Command: $JAVA $with_boot_jdk_jvmargs -version" >&5 + OUTPUT=`$JAVA $with_boot_jdk_jvmargs -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + boot_jdk_jvmargs="$boot_jdk_jvmargs $with_boot_jdk_jvmargs" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs" >&5 +$as_echo "$boot_jdk_jvmargs" >&6; } + + # For now, general JAVA_FLAGS are the same as the boot jdk jvmargs + JAVA_FLAGS=$boot_jdk_jvmargs + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command for big workloads" >&5 +$as_echo_n "checking flags for boot jdk java command for big workloads... " >&6; } + + # Starting amount of heap memory. + + $ECHO "Check if jvm arg is ok: -Xms64M" >&5 + $ECHO "Command: $JAVA -Xms64M -version" >&5 + OUTPUT=`$JAVA -Xms64M -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -Xms64M" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + # Maximum amount of heap memory. + # Maximum stack size. + JVM_MAX_HEAP=`expr $MEMORY_SIZE / 2` + if test "x$BUILD_NUM_BITS" = x32; then + if test "$JVM_MAX_HEAP" -gt "1100"; then + JVM_MAX_HEAP=1100 + elif test "$JVM_MAX_HEAP" -lt "512"; then + JVM_MAX_HEAP=512 + fi + STACK_SIZE=768 + else + # Running Javac on a JVM on a 64-bit machine, takes more space since 64-bit + # pointers are used. Apparently, we need to increase the heap and stack + # space for the jvm. More specifically, when running javac to build huge + # jdk batch + if test "$JVM_MAX_HEAP" -gt "1600"; then + JVM_MAX_HEAP=1600 + elif test "$JVM_MAX_HEAP" -lt "512"; then + JVM_MAX_HEAP=512 + fi + STACK_SIZE=1536 + fi + + $ECHO "Check if jvm arg is ok: -Xmx${JVM_MAX_HEAP}M" >&5 + $ECHO "Command: $JAVA -Xmx${JVM_MAX_HEAP}M -version" >&5 + OUTPUT=`$JAVA -Xmx${JVM_MAX_HEAP}M -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -Xmx${JVM_MAX_HEAP}M" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + $ECHO "Check if jvm arg is ok: -XX:ThreadStackSize=$STACK_SIZE" >&5 + $ECHO "Command: $JAVA -XX:ThreadStackSize=$STACK_SIZE -version" >&5 + OUTPUT=`$JAVA -XX:ThreadStackSize=$STACK_SIZE -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + boot_jdk_jvmargs_big="$boot_jdk_jvmargs_big -XX:ThreadStackSize=$STACK_SIZE" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_big" >&5 +$as_echo "$boot_jdk_jvmargs_big" >&6; } + + JAVA_FLAGS_BIG=$boot_jdk_jvmargs_big + + + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking flags for boot jdk java command for small workloads" >&5 +$as_echo_n "checking flags for boot jdk java command for small workloads... " >&6; } + + # Use serial gc for small short lived tools if possible + + $ECHO "Check if jvm arg is ok: -XX:+UseSerialGC" >&5 + $ECHO "Command: $JAVA -XX:+UseSerialGC -version" >&5 + OUTPUT=`$JAVA -XX:+UseSerialGC -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -XX:+UseSerialGC" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + $ECHO "Check if jvm arg is ok: -Xms32M" >&5 + $ECHO "Command: $JAVA -Xms32M -version" >&5 + OUTPUT=`$JAVA -Xms32M -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -Xms32M" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + $ECHO "Check if jvm arg is ok: -Xmx512M" >&5 + $ECHO "Command: $JAVA -Xmx512M -version" >&5 + OUTPUT=`$JAVA -Xmx512M -version 2>&1` + FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` + FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` + if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then + boot_jdk_jvmargs_small="$boot_jdk_jvmargs_small -Xmx512M" + JVM_ARG_OK=true + else + $ECHO "Arg failed:" >&5 + $ECHO "$OUTPUT" >&5 + JVM_ARG_OK=false + fi + + + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $boot_jdk_jvmargs_small" >&5 +$as_echo "$boot_jdk_jvmargs_small" >&6; } + + JAVA_FLAGS_SMALL=$boot_jdk_jvmargs_small + + + JAVA_TOOL_FLAGS_SMALL="" + for f in $JAVA_FLAGS_SMALL; do + JAVA_TOOL_FLAGS_SMALL="$JAVA_TOOL_FLAGS_SMALL -J$f" + done + + + # Setup smart javac (after cores and memory have been setup) @@ -49343,44 +50460,11 @@ fi as_fn_error $? "Could not execute server java: $SJAVAC_SERVER_JAVA" "$LINENO" 5 fi else - SJAVAC_SERVER_JAVA="" - # Hotspot specific options. - - $ECHO "Check if jvm arg is ok: -verbosegc" >&5 - $ECHO "Command: $JAVA -verbosegc -version" >&5 - OUTPUT=`$JAVA -verbosegc -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -verbosegc" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - # JRockit specific options. - - $ECHO "Check if jvm arg is ok: -Xverbose:gc" >&5 - $ECHO "Command: $JAVA -Xverbose:gc -version" >&5 - OUTPUT=`$JAVA -Xverbose:gc -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xverbose:gc" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - SJAVAC_SERVER_JAVA="$JAVA $SJAVAC_SERVER_JAVA" + SJAVAC_SERVER_JAVA="$JAVA" fi - if test "$MEMORY_SIZE" -gt "2500"; then + if test "$MEMORY_SIZE" -gt "3000"; then $ECHO "Check if jvm arg is ok: -d64" >&5 $ECHO "Command: $SJAVAC_SERVER_JAVA -d64 -version" >&5 @@ -49402,85 +50486,31 @@ fi fi fi + MX_VALUE=`expr $MEMORY_SIZE / 2` if test "$JVM_64BIT" = true; then - if test "$MEMORY_SIZE" -gt "17000"; then - - $ECHO "Check if jvm arg is ok: -Xms10G -Xmx10G" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms10G -Xmx10G -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms10G -Xmx10G -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms10G -Xmx10G" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - + # Set ms lower than mx since more than one instance of the server might + # get launched at the same time before they figure out which instance won. + MS_VALUE=512 + if test "$MX_VALUE" -gt "2048"; then + MX_VALUE=2048 fi - if test "$MEMORY_SIZE" -gt "10000" && test "$JVM_ARG_OK" = false; then - - $ECHO "Check if jvm arg is ok: -Xms6G -Xmx6G" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms6G -Xmx6G -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms6G -Xmx6G -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms6G -Xmx6G" - JVM_ARG_OK=true else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - fi - if test "$MEMORY_SIZE" -gt "5000" && test "$JVM_ARG_OK" = false; then - - $ECHO "Check if jvm arg is ok: -Xms1G -Xmx3G" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms1G -Xmx3G -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms1G -Xmx3G -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms1G -Xmx3G" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - fi - if test "$MEMORY_SIZE" -gt "3800" && test "$JVM_ARG_OK" = false; then - - $ECHO "Check if jvm arg is ok: -Xms1G -Xmx2500M" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms1G -Xmx2500M -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms1G -Xmx2500M -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms1G -Xmx2500M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - + MS_VALUE=256 + if test "$MX_VALUE" -gt "1500"; then + MX_VALUE=1500 fi fi - if test "$MEMORY_SIZE" -gt "2500" && test "$JVM_ARG_OK" = false; then + if test "$MX_VALUE" -lt "512"; then + MX_VALUE=512 + fi - $ECHO "Check if jvm arg is ok: -Xms1000M -Xmx1500M" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms1000M -Xmx1500M -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms1000M -Xmx1500M -version 2>&1` + $ECHO "Check if jvm arg is ok: -Xms${MS_VALUE}M -Xmx${MX_VALUE}M" >&5 + $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms${MS_VALUE}M -Xmx${MX_VALUE}M -version" >&5 + OUTPUT=`$SJAVAC_SERVER_JAVA -Xms${MS_VALUE}M -Xmx${MX_VALUE}M -version 2>&1` FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms1000M -Xmx1500M" + SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms${MS_VALUE}M -Xmx${MX_VALUE}M" JVM_ARG_OK=true else $ECHO "Arg failed:" >&5 @@ -49488,44 +50518,7 @@ fi JVM_ARG_OK=false fi - fi - if test "$MEMORY_SIZE" -gt "1000" && test "$JVM_ARG_OK" = false; then - $ECHO "Check if jvm arg is ok: -Xms400M -Xmx1100M" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms400M -Xmx1100M -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms400M -Xmx1100M -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms400M -Xmx1100M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - fi - if test "$JVM_ARG_OK" = false; then - - $ECHO "Check if jvm arg is ok: -Xms256M -Xmx512M" >&5 - $ECHO "Command: $SJAVAC_SERVER_JAVA -Xms256M -Xmx512M -version" >&5 - OUTPUT=`$SJAVAC_SERVER_JAVA -Xms256M -Xmx512M -version 2>&1` - FOUND_WARN=`$ECHO "$OUTPUT" | grep -i warn` - FOUND_VERSION=`$ECHO $OUTPUT | grep " version \""` - if test "x$FOUND_VERSION" != x && test "x$FOUND_WARN" = x; then - SJAVAC_SERVER_JAVA="$SJAVAC_SERVER_JAVA -Xms256M -Xmx512M" - JVM_ARG_OK=true - else - $ECHO "Arg failed:" >&5 - $ECHO "$OUTPUT" >&5 - JVM_ARG_OK=false - fi - - fi - - { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use sjavac" >&5 -$as_echo_n "checking whether to use sjavac... " >&6; } # Check whether --enable-sjavac was given. if test "${enable_sjavac+set}" = set; then : enableval=$enable_sjavac; ENABLE_SJAVAC="${enableval}" @@ -49533,6 +50526,13 @@ else ENABLE_SJAVAC='no' fi + if test "x$JVM_ARG_OK" = "xfalse"; then + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling sjavac" >&5 +$as_echo "$as_me: WARNING: Could not set -Xms${MS_VALUE}M -Xmx${MX_VALUE}M, disabling sjavac" >&2;} + ENABLE_SJAVAC=no; + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether to use sjavac" >&5 +$as_echo_n "checking whether to use sjavac... " >&6; } { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ENABLE_SJAVAC" >&5 $as_echo "$ENABLE_SJAVAC" >&6; } @@ -49903,7 +50903,7 @@ $as_echo "no, disabling ccaching of precompiled headers" >&6; } # Check for some common pitfalls - if test x"$OPENJDK_BUILD_OS" = xwindows; then + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.cygwin"; then file_to_test="$SRC_ROOT/LICENSE" if test `$STAT -c '%a' "$file_to_test"` -lt 400; then as_fn_error $? "Bad file permissions on src files. This is usually caused by cloning the repositories with a non cygwin hg in a directory not created in cygwin." "$LINENO" 5 @@ -51347,3 +52347,4 @@ $CHMOD +x $OUTPUT_ROOT/compare.sh printf "\n" fi + diff --git a/common/autoconf/help.m4 b/common/autoconf/help.m4 index 9ae7874fd6b..e1e792c3aa1 100644 --- a/common/autoconf/help.m4 +++ b/common/autoconf/help.m4 @@ -75,20 +75,18 @@ cygwin_help() { HELP_MSG="You might be able to fix this by running '$PKGHANDLER_COMMAND'." ;; freetype) - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - HELP_MSG="To install freetype, run: -wget \"http://gnuwin32.sourceforge.net/downlinks/freetype.php\" -O /tmp/freetype-setup.exe -chmod +x /tmp/freetype-setup.exe -/tmp/freetype-setup.exe -Follow GUI prompts, and install to default directory \"C:\Program Files (x86)\GnuWin32\". -After installation, locate lib/libfreetype.dll.a and make a copy with the name freetype.dll." - else - HELP_MSG="You need to build a 64-bit version of freetype. -This is not readily available. -You can find source code and build instructions on -http://www.freetype.org/ -If you put the resulting build in \"C:\Program Files\GnuWin32\", it will be found automatically." - fi + HELP_MSG=" +The freetype library can now be build during the configure process. +Download the freetype sources and unpack them into an arbitrary directory: + +wget http://download.savannah.gnu.org/releases/freetype/freetype-2.5.3.tar.gz +tar -xzf freetype-2.5.3.tar.gz + +Then run configure with '--with-freetype-src='. This will +automatically build the freetype library into '/lib64' for 64-bit +builds or into '/lib32' for 32-bit builds. +Afterwards you can always use '--with-freetype-include=/include' +and '--with-freetype-lib=/lib[32|64]' for other builds." ;; esac } diff --git a/common/autoconf/libraries.m4 b/common/autoconf/libraries.m4 index 3a689ef62ee..5f9eabf250b 100644 --- a/common/autoconf/libraries.m4 +++ b/common/autoconf/libraries.m4 @@ -247,12 +247,95 @@ AC_DEFUN_ONCE([LIB_SETUP_CUPS], ]) +AC_DEFUN([LIB_BUILD_FREETYPE], +[ + FREETYPE_SRC_PATH="$1" + BUILD_FREETYPE=yes + + # Check if the freetype sources are acessible.. + if ! test -d $FREETYPE_SRC_PATH; then + AC_MSG_WARN([--with-freetype-src specified, but can't find path "$FREETYPE_SRC_PATH" - ignoring --with-freetype-src]) + BUILD_FREETYPE=no + fi + # ..and contain a vc2010 project file + vcxproj_path="$FREETYPE_SRC_PATH/builds/windows/vc2010/freetype.vcxproj" + if test "x$BUILD_FREETYPE" = xyes && ! test -s $vcxproj_path; then + AC_MSG_WARN([Can't find project file $vcxproj_path (you may try a newer freetype version) - ignoring --with-freetype-src]) + BUILD_FREETYPE=no + fi + # Now check if configure found a version of 'msbuild.exe' + if test "x$BUILD_FREETYPE" = xyes && test "x$MSBUILD" == x ; then + AC_MSG_WARN([Can't find an msbuild.exe executable (you may try to install .NET 4.0) - ignoring --with-freetype-src]) + BUILD_FREETYPE=no + fi + + # Ready to go.. + if test "x$BUILD_FREETYPE" = xyes; then + + # msbuild requires trailing slashes for output directories + freetype_lib_path="$FREETYPE_SRC_PATH/lib$OPENJDK_TARGET_CPU_BITS/" + freetype_lib_path_unix="$freetype_lib_path" + freetype_obj_path="$FREETYPE_SRC_PATH/obj$OPENJDK_TARGET_CPU_BITS/" + BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(vcxproj_path) + BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(freetype_lib_path) + BASIC_WINDOWS_REWRITE_AS_WINDOWS_MIXED_PATH(freetype_obj_path) + if test "x$OPENJDK_TARGET_CPU_BITS" = x64; then + freetype_platform=x64 + else + freetype_platform=win32 + fi + + # The original freetype project file is for VS 2010 (i.e. 'v100'), + # so we have to adapt the toolset if building with any other toolsed (i.e. SDK). + # Currently 'PLATFORM_TOOLSET' is set in 'TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT'/ + # 'TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT' in toolchain_windows.m4 + AC_MSG_NOTICE([Trying to compile freetype sources with PlatformToolset=$PLATFORM_TOOLSET to $freetype_lib_path_unix ...]) + + # First we try to build the freetype.dll + $ECHO -e "@echo off\n"\ + "$MSBUILD $vcxproj_path "\ + "/p:PlatformToolset=$PLATFORM_TOOLSET "\ + "/p:Configuration=\"Release Multithreaded\" "\ + "/p:Platform=$freetype_platform "\ + "/p:ConfigurationType=DynamicLibrary "\ + "/p:TargetName=freetype "\ + "/p:OutDir=\"$freetype_lib_path\" "\ + "/p:IntDir=\"$freetype_obj_path\" > freetype.log" > freetype.bat + cmd /c freetype.bat + + if test -s "$freetype_lib_path_unix/freetype.dll"; then + # If that succeeds we also build freetype.lib + $ECHO -e "@echo off\n"\ + "$MSBUILD $vcxproj_path "\ + "/p:PlatformToolset=$PLATFORM_TOOLSET "\ + "/p:Configuration=\"Release Multithreaded\" "\ + "/p:Platform=$freetype_platform "\ + "/p:ConfigurationType=StaticLibrary "\ + "/p:TargetName=freetype "\ + "/p:OutDir=\"$freetype_lib_path\" "\ + "/p:IntDir=\"$freetype_obj_path\" >> freetype.log" > freetype.bat + cmd /c freetype.bat + + if test -s "$freetype_lib_path_unix/freetype.lib"; then + # Once we build both, lib and dll, set freetype lib and include path appropriately + POTENTIAL_FREETYPE_INCLUDE_PATH="$FREETYPE_SRC_PATH/include" + POTENTIAL_FREETYPE_LIB_PATH="$freetype_lib_path_unix" + AC_MSG_NOTICE([Compiling freetype sources succeeded! (see freetype.log for build results)]) + else + BUILD_FREETYPE=no + fi + else + BUILD_FREETYPE=no + fi + fi +]) + AC_DEFUN([LIB_CHECK_POTENTIAL_FREETYPE], [ POTENTIAL_FREETYPE_INCLUDE_PATH="$1" POTENTIAL_FREETYPE_LIB_PATH="$2" METHOD="$3" - + # First check if the files exists. if test -s "$POTENTIAL_FREETYPE_INCLUDE_PATH/ft2build.h"; then # We found an arbitrary include file. That's a good sign. @@ -305,6 +388,8 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE], [specify directory for the freetype include files])]) AC_ARG_WITH(freetype-lib, [AS_HELP_STRING([--with-freetype-lib], [specify directory for the freetype library])]) + AC_ARG_WITH(freetype-src, [AS_HELP_STRING([--with-freetype-src], + [specify directory with freetype sources to automatically build the library (experimental, Windows-only)])]) AC_ARG_ENABLE(freetype-bundling, [AS_HELP_STRING([--disable-freetype-bundling], [disable bundling of the freetype library with the build result @<:@enabled on Windows or when using --with-freetype, disabled otherwise@:>@])]) @@ -313,7 +398,7 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE], FREETYPE_BUNDLE_LIB_PATH= if test "x$FREETYPE_NOT_NEEDED" = xyes; then - if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x; then + if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x || test "x$with_freetype_src" != x; then AC_MSG_WARN([freetype not used, so --with-freetype is ignored]) fi if test "x$enable_freetype_bundling" != x; then @@ -324,6 +409,25 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE], BUNDLE_FREETYPE="$enable_freetype_bundling" + if test "x$with_freetype_src" != x; then + if test "x$OPENJDK_TARGET_OS" = xwindows; then + # Try to build freetype if --with-freetype-src was given on Windows + LIB_BUILD_FREETYPE([$with_freetype_src]) + if test "x$BUILD_FREETYPE" = xyes; then + # Okay, we built it. Check that it works. + LIB_CHECK_POTENTIAL_FREETYPE($POTENTIAL_FREETYPE_INCLUDE_PATH, $POTENTIAL_FREETYPE_LIB_PATH, [--with-freetype-src]) + if test "x$FOUND_FREETYPE" != xyes; then + AC_MSG_ERROR([Can not use the built freetype at location given by --with-freetype-src]) + fi + else + AC_MSG_NOTICE([User specified --with-freetype-src but building freetype failed. (see freetype.log for build results)]) + AC_MSG_ERROR([Consider building freetype manually and using --with-freetype instead.]) + fi + else + AC_MSG_WARN([--with-freetype-src is currently only supported on Windows - ignoring]) + fi + fi + if test "x$with_freetype" != x || test "x$with_freetype_include" != x || test "x$with_freetype_lib" != x; then # User has specified settings @@ -331,12 +435,12 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE], # If not specified, default is to bundle freetype BUNDLE_FREETYPE=yes fi - + if test "x$with_freetype" != x; then POTENTIAL_FREETYPE_INCLUDE_PATH="$with_freetype/include" POTENTIAL_FREETYPE_LIB_PATH="$with_freetype/lib" fi - + # Allow --with-freetype-lib and --with-freetype-include to override if test "x$with_freetype_include" != x; then POTENTIAL_FREETYPE_INCLUDE_PATH="$with_freetype_include" @@ -468,7 +572,7 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE], FREETYPE_CFLAGS="-I$FREETYPE_INCLUDE_PATH" fi fi - + if test "x$FREETYPE_LIBS" = x; then BASIC_FIXUP_PATH(FREETYPE_LIB_PATH) if test "x$OPENJDK_TARGET_OS" = xwindows; then @@ -484,7 +588,7 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE], PREV_CXXCFLAGS="$CXXFLAGS" PREV_LIBS="$LIBS" PREV_CXX="$CXX" - CXXFLAGS="$CXXFLAGS $FREETYPE_CFLAGS" + CXXFLAGS="$CXXFLAGS $FREETYPE_CFLAGS" LIBS="$LIBS $FREETYPE_LIBS" CXX="$FIXPATH $CXX" AC_LINK_IFELSE([AC_LANG_SOURCE([[ @@ -502,9 +606,9 @@ AC_DEFUN_ONCE([LIB_SETUP_FREETYPE], AC_MSG_RESULT([no]) AC_MSG_NOTICE([Could not compile and link with freetype. This might be a 32/64-bit mismatch.]) AC_MSG_NOTICE([Using FREETYPE_CFLAGS=$FREETYPE_CFLAGS and FREETYPE_LIBS=$FREETYPE_LIBS]) - + HELP_MSG_MISSING_DEPENDENCY([freetype]) - + AC_MSG_ERROR([Can not continue without freetype. $HELP_MSG]) ] ) diff --git a/common/autoconf/platform.m4 b/common/autoconf/platform.m4 index ead832d5050..4eacb397cbe 100644 --- a/common/autoconf/platform.m4 +++ b/common/autoconf/platform.m4 @@ -173,6 +173,7 @@ AC_DEFUN([PLATFORM_EXTRACT_TARGET_AND_BUILD], OPENJDK_BUILD_CPU_ENDIAN="$VAR_CPU_ENDIAN" AC_SUBST(OPENJDK_BUILD_OS) AC_SUBST(OPENJDK_BUILD_OS_API) + AC_SUBST(OPENJDK_BUILD_OS_ENV) AC_SUBST(OPENJDK_BUILD_CPU) AC_SUBST(OPENJDK_BUILD_CPU_ARCH) AC_SUBST(OPENJDK_BUILD_CPU_BITS) @@ -194,6 +195,7 @@ AC_DEFUN([PLATFORM_EXTRACT_TARGET_AND_BUILD], OPENJDK_TARGET_CPU_ENDIAN="$VAR_CPU_ENDIAN" AC_SUBST(OPENJDK_TARGET_OS) AC_SUBST(OPENJDK_TARGET_OS_API) + AC_SUBST(OPENJDK_TARGET_OS_ENV) AC_SUBST(OPENJDK_TARGET_CPU) AC_SUBST(OPENJDK_TARGET_CPU_ARCH) AC_SUBST(OPENJDK_TARGET_CPU_BITS) diff --git a/common/autoconf/spec.gmk.in b/common/autoconf/spec.gmk.in index 315c10615e4..e85c830783c 100644 --- a/common/autoconf/spec.gmk.in +++ b/common/autoconf/spec.gmk.in @@ -106,6 +106,7 @@ OPENJDK_TARGET_OS_EXPORT_DIR:=@OPENJDK_TARGET_OS_EXPORT_DIR@ # When not cross-compiling, it is the same as the target. OPENJDK_BUILD_OS:=@OPENJDK_BUILD_OS@ OPENJDK_BUILD_OS_API:=@OPENJDK_BUILD_OS_API@ +OPENJDK_BUILD_OS_ENV:=@OPENJDK_BUILD_OS_ENV@ OPENJDK_BUILD_CPU:=@OPENJDK_BUILD_CPU@ OPENJDK_BUILD_CPU_ARCH:=@OPENJDK_BUILD_CPU_ARCH@ diff --git a/common/autoconf/toolchain.m4 b/common/autoconf/toolchain.m4 index f380bf446ad..db0a253a207 100644 --- a/common/autoconf/toolchain.m4 +++ b/common/autoconf/toolchain.m4 @@ -557,6 +557,14 @@ AC_DEFUN_ONCE([TOOLCHAIN_DETECT_TOOLCHAIN_EXTRA], BASIC_FIXUP_EXECUTABLE(RC) AC_CHECK_PROG([DUMPBIN], [dumpbin], [dumpbin],,,) BASIC_FIXUP_EXECUTABLE(DUMPBIN) + # We need to check for 'msbuild.exe' because at the place where we expect to + # find 'msbuild.exe' there's also a directory called 'msbuild' and configure + # won't find the 'msbuild.exe' executable in that case (and the + # 'ac_executable_extensions' is unusable due to performance reasons). + # Notice that we intentionally don't fix up the path to MSBUILD because we + # will call it in a DOS shell during freetype detection on Windows (see + # 'LIB_SETUP_FREETYPE' in "libraries.m4" + AC_CHECK_PROG([MSBUILD], [msbuild.exe], [msbuild.exe],,,) fi if test "x$OPENJDK_TARGET_OS" = xsolaris; then diff --git a/common/autoconf/toolchain_windows.m4 b/common/autoconf/toolchain_windows.m4 index b4888a46ac5..380f7dd4054 100644 --- a/common/autoconf/toolchain_windows.m4 +++ b/common/autoconf/toolchain_windows.m4 @@ -33,6 +33,10 @@ AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_VISUAL_STUDIO_ROOT], if test -f "$VS100BASE/$VCVARSFILE"; then AC_MSG_NOTICE([Found Visual Studio installation at $VS100BASE using $METHOD]) VS_ENV_CMD="$VS100BASE/$VCVARSFILE" + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be one of 'v100', 'v110' or 'v120' for VS 2010, 2012 or VS2013 + # TODO: improve detection for other versions of VS + PLATFORM_TOOLSET="v100" else AC_MSG_NOTICE([Found Visual Studio installation at $VS100BASE using $METHOD]) AC_MSG_NOTICE([Warning: $VCVARSFILE is missing, this is probably Visual Studio Express. Ignoring]) @@ -61,6 +65,10 @@ AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_WIN_SDK_ROOT], else VS_ENV_ARGS="/x64" fi + # PLATFORM_TOOLSET is used during the compilation of the freetype sources (see + # 'LIB_BUILD_FREETYPE' in libraries.m4) and must be 'Windows7.1SDK' for Windows7.1SDK + # TODO: improve detection for other versions of SDK + PLATFORM_TOOLSET="Windows7.1SDK" else AC_MSG_NOTICE([Found Windows SDK installation at $WIN_SDK_BASE using $METHOD]) AC_MSG_NOTICE([Warning: Installation is broken, SetEnv.Cmd is missing. Ignoring]) @@ -244,12 +252,22 @@ AC_DEFUN([TOOLCHAIN_CHECK_POSSIBLE_MSVCR_DLL], # Need to check if the found msvcr is correct architecture AC_MSG_CHECKING([found msvcr100.dll architecture]) MSVCR_DLL_FILETYPE=`$FILE -b "$POSSIBLE_MSVCR_DLL"` - if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then - CORRECT_MSVCR_ARCH=386 + if test "x$OPENJDK_BUILD_OS_ENV" = "xwindows.msys"; then + # The MSYS 'file' command returns "PE32 executable for MS Windows (DLL) (GUI) Intel 80386 32-bit" + # on x32 and "PE32+ executable for MS Windows (DLL) (GUI) Mono/.Net assembly" on x64 systems. + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH="PE32 executable" + else + CORRECT_MSVCR_ARCH="PE32+ executable" + fi else - CORRECT_MSVCR_ARCH=x86-64 + if test "x$OPENJDK_TARGET_CPU_BITS" = x32; then + CORRECT_MSVCR_ARCH=386 + else + CORRECT_MSVCR_ARCH=x86-64 + fi fi - if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP $CORRECT_MSVCR_ARCH 2>&1 > /dev/null; then + if $ECHO "$MSVCR_DLL_FILETYPE" | $GREP "$CORRECT_MSVCR_ARCH" 2>&1 > /dev/null; then AC_MSG_RESULT([ok]) MSVCR_DLL="$POSSIBLE_MSVCR_DLL" AC_MSG_CHECKING([for msvcr100.dll]) diff --git a/common/bin/hgforest.sh b/common/bin/hgforest.sh index e7fbd1fe13f..5bf586bc13c 100644 --- a/common/bin/hgforest.sh +++ b/common/bin/hgforest.sh @@ -77,6 +77,11 @@ do shift done +# debug mode +if [ "${HGFOREST_DEBUG:-false}" = "true" ] ; then + global_opts="${global_opts} --debug" +fi + # silence standard output? if [ ${qflag} = "true" ] ; then global_opts="${global_opts} -q" @@ -89,14 +94,26 @@ if [ ${vflag} = "true" ] ; then fi # Make sure we have a command. -if [ $# -lt 1 -o -z "${1:-}" ] ; then - echo "ERROR: No command to hg supplied!" - usage +if [ ${#} -lt 1 -o -z "${1:-}" ] ; then + echo "ERROR: No command to hg supplied!" > ${status_output} + usage > ${status_output} fi -command="$1"; shift +# grab command +command="${1}"; shift + +if [ ${vflag} = "true" ] ; then + echo "# Mercurial command: ${command}" > ${status_output} +fi + + +# capture command options and arguments (if any) command_args="${@:-}" +if [ ${vflag} = "true" ] ; then + echo "# Mercurial command arguments: ${command_args}" > ${status_output} +fi + # Clean out the temporary directory that stores the pid files. tmp=/tmp/forest.$$ rm -f -r ${tmp} @@ -104,7 +121,8 @@ mkdir -p ${tmp} if [ "${HGFOREST_DEBUG:-false}" = "true" ] ; then - echo "DEBUG: temp files are in: ${tmp}" + # ignores redirection. + echo "DEBUG: temp files are in: ${tmp}" >&2 fi # Check if we can use fifos for monitoring sub-process completion. @@ -377,21 +395,33 @@ else fi fi done + + if [ ${have_fifos} = "true" ]; then + # done with the fifo + exec 3>&- + fi fi # Wait for all subprocesses to complete wait # Terminate with exit 0 only if all subprocesses were successful +# Terminate with highest exit code of subprocesses ec=0 if [ -d ${tmp} ]; then rcfiles="`(ls -a ${tmp}/*.pid.rc 2> /dev/null) || echo ''`" for rc in ${rcfiles} ; do exit_code=`cat ${rc} | tr -d ' \n\r'` if [ "${exit_code}" != "0" ] ; then + if [ ${exit_code} -gt 1 ]; then + # mercurial exit codes greater than "1" signal errors. repo="`echo ${rc} | sed -e 's@^'${tmp}'@@' -e 's@/*\([^/]*\)\.pid\.rc$@\1@' -e 's@_@/@g'`" echo "WARNING: ${repo} exited abnormally (${exit_code})" > ${status_output} - ec=1 + fi + if [ ${exit_code} -gt ${ec} ]; then + # assume that larger exit codes are more significant + ec=${exit_code} + fi fi done fi diff --git a/corba/.hgignore b/corba/.hgignore index e05f09317c5..5e6b22f24ee 100644 --- a/corba/.hgignore +++ b/corba/.hgignore @@ -1,5 +1,6 @@ ^build/ ^dist/ +^webrev /nbproject/private/ ^.hgtip .DS_Store diff --git a/corba/.hgtags b/corba/.hgtags index d7401bcb630..210911039ff 100644 --- a/corba/.hgtags +++ b/corba/.hgtags @@ -269,3 +269,7 @@ ddc07abf4307855c0dc904cc5c96cc764023a930 jdk9-b22 8a44142bb7fc8118f70f91a1b97c12dfc50563ee jdk9-b24 da08cca6b97f41b7081a3e176dcb400af6e4bb26 jdk9-b25 6c777df597bbf5abba3488d44c401edfe73c74af jdk9-b26 +7e06bf1dcb0907b80ddf59315426ce9ce775e56d jdk9-b27 +a00b04ef067e39f50b9a0fea6f1904e35d632a73 jdk9-b28 +163a9cd806fd09970baf1f5f42b92a3cfe7ee945 jdk9-b29 +98967ae6ae53ebf15615e07cd5a6b1ae04dfd84c jdk9-b30 diff --git a/corba/make/GensrcCorba.gmk b/corba/make/GensrcCorba.gmk index 8b814238272..1951cd43e37 100644 --- a/corba/make/GensrcCorba.gmk +++ b/corba/make/GensrcCorba.gmk @@ -50,8 +50,9 @@ $(eval $(call SetupJavaCompilation,BUILD_IDLJ, \ INCLUDES := com/sun/tools/corba/se/idl, \ EXCLUDE_FILES := ResourceBundleUtil.java)) +# Force the language to english for predictable source code generation. TOOL_IDLJ_CMD := $(JAVA) -cp $(CORBA_OUTPUTDIR)/idlj_classes \ - com.sun.tools.corba.se.idl.toJavaPortable.Compile + -Duser.language=en com.sun.tools.corba.se.idl.toJavaPortable.Compile ################################################################################ diff --git a/corba/src/java.corba/share/classes/org/omg/CORBA/FloatSeqHelper.java b/corba/src/java.corba/share/classes/org/omg/CORBA/FloatSeqHelper.java index ad02ae3b56a..8cf9684c585 100644 --- a/corba/src/java.corba/share/classes/org/omg/CORBA/FloatSeqHelper.java +++ b/corba/src/java.corba/share/classes/org/omg/CORBA/FloatSeqHelper.java @@ -38,11 +38,11 @@ package org.omg.CORBA; * OMG specifications : * */ diff --git a/get_source.sh b/get_source.sh index 5e874d1cb51..72049bdec8a 100644 --- a/get_source.sh +++ b/get_source.sh @@ -67,7 +67,7 @@ if [ "x$hgwhere" = "x" ]; then error "Could not locate Mercurial command" fi -hgversion="`hg --version 2> /dev/null | sed -n -e 's@^Mercurial Distributed SCM (version \([^+]*\).*)\$@\1@p'`" +hgversion="`LANGUAGE=en hg --version 2> /dev/null | sed -n -e 's@^Mercurial Distributed SCM (version \([^+]*\).*)\$@\1@p'`" if [ "x${hgversion}" = "x" ] ; then error "Could not determine Mercurial version of $hgwhere" fi diff --git a/hotspot/.hgignore b/hotspot/.hgignore index c652de177bf..e9ce602582b 100644 --- a/hotspot/.hgignore +++ b/hotspot/.hgignore @@ -1,5 +1,6 @@ ^build/ ^dist/ +^webrev /nbproject/private/ ^src/share/tools/hsdis/build/ ^src/share/tools/IdealGraphVisualizer/[a-zA-Z0-9]*/build/ diff --git a/hotspot/.hgtags b/hotspot/.hgtags index 2dbb04816d9..a7b7e9b5c01 100644 --- a/hotspot/.hgtags +++ b/hotspot/.hgtags @@ -429,3 +429,7 @@ dd472cdacc32e3afc7c5bfa7ef16ea0e0befb7fa jdk9-b23 dde2d03b0ea46a27650839e3a1d212c7c1f7b4c8 jdk9-b24 6de94e8693240cec8aae11f6b42f43433456a733 jdk9-b25 48b95a073d752d6891cc0d1d2836b321ecf3ce0c jdk9-b26 +f95347244306affc32ce3056f27ceff7b2100810 jdk9-b27 +657294869d7ff063e055f5492cab7ce5612ca851 jdk9-b28 +deb29e92f68ace2808a36ecfa18c7d61dcb645bb jdk9-b29 +5c722dffbc0f34eb8d903dca7b261e52248fa17e jdk9-b30 diff --git a/hotspot/make/Makefile b/hotspot/make/Makefile index a45203e5cbd..d9c0dcf8125 100644 --- a/hotspot/make/Makefile +++ b/hotspot/make/Makefile @@ -95,6 +95,7 @@ MINIMAL1_VM_TARGETS=productminimal1 fastdebugminimal1 debugminimal1 COMMON_VM_PRODUCT_TARGETS=product product1 docs export_product COMMON_VM_FASTDEBUG_TARGETS=fastdebug fastdebug1 docs export_fastdebug COMMON_VM_DEBUG_TARGETS=debug debug1 docs export_debug +COMMON_VM_OPTIMIZED_TARGETS=optimized optimized1 docs export_optimized # JDK directory list JDK_DIRS=bin include jre lib demo @@ -111,20 +112,21 @@ ifdef BUILD_CLIENT_ONLY all_product: product1 docs export_product all_fastdebug: fastdebug1 docs export_fastdebug all_debug: debug1 docs export_debug +all_optimized: optimized1 docs export_optimized else ifeq ($(MACOSX_UNIVERSAL),true) all_product: universal_product all_fastdebug: universal_fastdebug all_debug: universal_debug +all_optimized: universal_optimized else all_product: $(COMMON_VM_PRODUCT_TARGETS) all_fastdebug: $(COMMON_VM_FASTDEBUG_TARGETS) all_debug: $(COMMON_VM_DEBUG_TARGETS) +all_optimized: $(COMMON_VM_OPTIMIZED_TARGETS) endif endif -all_optimized: optimized optimized1 docs export_optimized - allzero: all_productzero all_fastdebugzero all_productzero: productzero docs export_product all_fastdebugzero: fastdebugzero docs export_fastdebug diff --git a/hotspot/make/bsd/makefiles/universal.gmk b/hotspot/make/bsd/makefiles/universal.gmk index 44d57d963aa..12a34d70157 100644 --- a/hotspot/make/bsd/makefiles/universal.gmk +++ b/hotspot/make/bsd/makefiles/universal.gmk @@ -25,6 +25,8 @@ # macosx universal builds universal_product: $(MAKE) MACOSX_UNIVERSAL=true all_product_universal +universal_optimized: + $(MAKE) MACOSX_UNIVERSAL=true all_optimized_universal universal_fastdebug: $(MAKE) MACOSX_UNIVERSAL=true all_fastdebug_universal universal_debug: @@ -36,6 +38,10 @@ all_product_universal: # $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_PRODUCT_TARGETS) $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_PRODUCT_TARGETS) $(QUIETLY) $(MAKE) BUILD_FLAVOR=product EXPORT_SUBDIR= universalize +all_optimized_universal: +# $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_OPTIMIZED_TARGETS) + $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_OPTIMIZED_TARGETS) + $(QUIETLY) $(MAKE) BUILD_FLAVOR=optimized EXPORT_SUBDIR=/optimized universalize all_fastdebug_universal: # $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=32 $(COMMON_VM_FASTDEBUG_TARGETS) $(QUIETLY) $(MAKE) ARCH_DATA_MODEL=64 $(COMMON_VM_FASTDEBUG_TARGETS) @@ -98,13 +104,15 @@ copy_universal: export_product_jdk:: $(MAKE) EXPORT_SUBDIR= export_universal export_optimized_jdk:: - $(MAKE) EXPORT_SUBDIR= export_universal + $(MAKE) EXPORT_SUBDIR=/optimized export_universal export_fastdebug_jdk:: $(MAKE) EXPORT_SUBDIR=/fastdebug export_universal export_debug_jdk:: $(MAKE) EXPORT_SUBDIR=/debug export_universal copy_product_jdk:: $(MAKE) COPY_SUBDIR= copy_universal +copy_optimized_jdk:: + $(MAKE) COPY_SUBDIR=/optimized copy_universal copy_fastdebug_jdk:: $(MAKE) COPY_SUBDIR=/fastdebug copy_universal copy_debug_jdk:: @@ -112,5 +120,6 @@ copy_debug_jdk:: .PHONY: universal_product universal_fastdebug universal_debug \ all_product_universal all_fastdebug_universal all_debug_universal \ + universal_optimized all_optimized_universal \ universalize export_universal copy_universal \ $(UNIVERSAL_LIPO_LIST) $(UNIVERSAL_COPY_LIST) diff --git a/hotspot/make/solaris/makefiles/vm.make b/hotspot/make/solaris/makefiles/vm.make index 609a76e1930..0448026ab9e 100644 --- a/hotspot/make/solaris/makefiles/vm.make +++ b/hotspot/make/solaris/makefiles/vm.make @@ -143,7 +143,7 @@ else LIBS += -lsocket -lsched -ldl $(LIBM) -lthread -lc -ldemangle endif # sparcWorks -LIBS += -lkstat +LIBS += -lkstat -lpicl # By default, link the *.o into the library, not the executable. LINK_INTO$(LINK_INTO) = LIBJVM diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp index 91a9f76af4c..ee2be7dd76d 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.cpp @@ -32,6 +32,7 @@ int VM_Version::_features = VM_Version::unknown_m; const char* VM_Version::_features_str = ""; +unsigned int VM_Version::_L2_cache_line_size = 0; void VM_Version::initialize() { _features = determine_features(); @@ -192,7 +193,7 @@ void VM_Version::initialize() { } assert(BlockZeroingLowLimit > 0, "invalid value"); - if (has_block_zeroing()) { + if (has_block_zeroing() && cache_line_size > 0) { if (FLAG_IS_DEFAULT(UseBlockZeroing)) { FLAG_SET_DEFAULT(UseBlockZeroing, true); } @@ -202,7 +203,7 @@ void VM_Version::initialize() { } assert(BlockCopyLowLimit > 0, "invalid value"); - if (has_block_zeroing()) { // has_blk_init() && is_T4(): core's local L2 cache + if (has_block_zeroing() && cache_line_size > 0) { // has_blk_init() && is_T4(): core's local L2 cache if (FLAG_IS_DEFAULT(UseBlockCopy)) { FLAG_SET_DEFAULT(UseBlockCopy, true); } @@ -252,49 +253,6 @@ void VM_Version::initialize() { // buf is started with ", " or is empty _features_str = os::strdup(strlen(buf) > 2 ? buf + 2 : buf); - // There are three 64-bit SPARC families that do not overlap, e.g., - // both is_ultra3() and is_sparc64() cannot be true at the same time. - // Within these families, there can be more than one chip, e.g., - // is_T4() and is_T7() machines are also is_niagara(). - if (is_ultra3()) { - assert(_L1_data_cache_line_size == 0, "overlap with Ultra3 family"); - // Ref: UltraSPARC III Cu Processor - _L1_data_cache_line_size = 64; - } - if (is_niagara()) { - assert(_L1_data_cache_line_size == 0, "overlap with niagara family"); - // All Niagara's are sun4v's, but not all sun4v's are Niagaras, e.g., - // Fujitsu SPARC64 is sun4v, but we don't want it in this block. - // - // Ref: UltraSPARC T1 Supplement to the UltraSPARC Architecture 2005 - // Appendix F.1.3.1 Cacheable Accesses - // -> 16-byte L1 cache line size - // - // Ref: UltraSPARC T2: A Highly-Threaded, Power-Efficient, SPARC SOC - // Section III: SPARC Processor Core - // -> 16-byte L1 cache line size - // - // Ref: Oracle's SPARC T4-1, SPARC T4-2, SPARC T4-4, and SPARC T4-1B Server Architecture - // Section SPARC T4 Processor Cache Architecture - // -> 32-byte L1 cache line size (no longer see that info on this ref) - // - // XXX - still need a T7 reference here - // - if (is_T7()) { // T7 or newer - _L1_data_cache_line_size = 64; - } else if (is_T4()) { // T4 or newer (until T7) - _L1_data_cache_line_size = 32; - } else { // T1 or newer (until T4) - _L1_data_cache_line_size = 16; - } - } - if (is_sparc64()) { - guarantee(_L1_data_cache_line_size == 0, "overlap with SPARC64 family"); - // Ref: Fujitsu SPARC64 VII Processor - // Section 4 Cache System - _L1_data_cache_line_size = 64; - } - // UseVIS is set to the smallest of what hardware supports and what // the command line requires. I.e., you cannot set UseVIS to 3 on // older UltraSparc which do not support it. @@ -401,6 +359,7 @@ void VM_Version::initialize() { #ifndef PRODUCT if (PrintMiscellaneous && Verbose) { tty->print_cr("L1 data cache line size: %u", L1_data_cache_line_size()); + tty->print_cr("L2 cache line size: %u", L2_cache_line_size()); tty->print("Allocation"); if (AllocatePrefetchStyle <= 0) { tty->print_cr(": no prefetching"); diff --git a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp index b20f8a69992..fa823863bdb 100644 --- a/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp +++ b/hotspot/src/cpu/sparc/vm/vm_version_sparc.hpp @@ -96,6 +96,9 @@ protected: static int _features; static const char* _features_str; + static unsigned int _L2_cache_line_size; + static unsigned int L2_cache_line_size() { return _L2_cache_line_size; } + static void print_features(); static int determine_features(); static int platform_features(int features); @@ -167,9 +170,8 @@ public: static const char* cpu_features() { return _features_str; } - static intx prefetch_data_size() { - return is_T4() && !is_T7() ? 32 : 64; // default prefetch block size on sparc - } + // default prefetch block size on sparc + static intx prefetch_data_size() { return L2_cache_line_size(); } // Prefetch static intx prefetch_copy_interval_in_bytes() { diff --git a/hotspot/src/cpu/x86/vm/assembler_x86.hpp b/hotspot/src/cpu/x86/vm/assembler_x86.hpp index 2ac9df8c927..ef16f27538f 100644 --- a/hotspot/src/cpu/x86/vm/assembler_x86.hpp +++ b/hotspot/src/cpu/x86/vm/assembler_x86.hpp @@ -26,6 +26,7 @@ #define CPU_X86_VM_ASSEMBLER_X86_HPP #include "asm/register.hpp" +#include "vm_version_x86.hpp" class BiasedLockingCounters; @@ -1292,14 +1293,34 @@ private: if (order_constraint & StoreLoad) { // All usable chips support "locked" instructions which suffice // as barriers, and are much faster than the alternative of - // using cpuid instruction. We use here a locked add [esp],0. + // using cpuid instruction. We use here a locked add [esp-C],0. // This is conveniently otherwise a no-op except for blowing - // flags. + // flags, and introducing a false dependency on target memory + // location. We can't do anything with flags, but we can avoid + // memory dependencies in the current method by locked-adding + // somewhere else on the stack. Doing [esp+C] will collide with + // something on stack in current method, hence we go for [esp-C]. + // It is convenient since it is almost always in data cache, for + // any small C. We need to step back from SP to avoid data + // dependencies with other things on below SP (callee-saves, for + // example). Without a clear way to figure out the minimal safe + // distance from SP, it makes sense to step back the complete + // cache line, as this will also avoid possible second-order effects + // with locked ops against the cache line. Our choice of offset + // is bounded by x86 operand encoding, which should stay within + // [-128; +127] to have the 8-byte displacement encoding. + // // Any change to this code may need to revisit other places in // the code where this idiom is used, in particular the // orderAccess code. + + int offset = -VM_Version::L1_line_size(); + if (offset < -128) { + offset = -128; + } + lock(); - addl(Address(rsp, 0), 0);// Assert the lock# signal here + addl(Address(rsp, offset), 0);// Assert the lock# signal here } } } diff --git a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp index 8573cf33e73..da8f4448d46 100644 --- a/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp +++ b/hotspot/src/os_cpu/aix_ppc/vm/os_aix_ppc.cpp @@ -563,3 +563,8 @@ void os::verify_stack_alignment() { assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment"); } #endif + +int os::extra_bang_size_in_bytes() { + // PPC does not require the additional stack bang. + return 0; +} diff --git a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp index 50051d7c699..a052d1150a9 100644 --- a/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp +++ b/hotspot/src/os_cpu/bsd_x86/vm/os_bsd_x86.cpp @@ -1030,3 +1030,8 @@ void os::setup_fpu() { void os::verify_stack_alignment() { } #endif + +int os::extra_bang_size_in_bytes() { + // JDK-8050147 requires the full cache line bang for x86. + return VM_Version::L1_line_size(); +} diff --git a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp index c857b552689..77c3dcdea64 100644 --- a/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp +++ b/hotspot/src/os_cpu/bsd_zero/vm/os_bsd_zero.cpp @@ -465,3 +465,8 @@ extern "C" { void os::verify_stack_alignment() { } #endif + +int os::extra_bang_size_in_bytes() { + // Zero does not require an additional stack bang. + return 0; +} diff --git a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp index d7fd74d219a..6a243c2a1ac 100644 --- a/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp +++ b/hotspot/src/os_cpu/linux_ppc/vm/os_linux_ppc.cpp @@ -612,3 +612,8 @@ void os::verify_stack_alignment() { assert(((intptr_t)os::current_stack_pointer() & (StackAlignmentInBytes-1)) == 0, "incorrect stack alignment"); } #endif + +int os::extra_bang_size_in_bytes() { + // PPC does not require the additional stack bang. + return 0; +} diff --git a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp index 14194e44947..f76c0c059fb 100644 --- a/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp +++ b/hotspot/src/os_cpu/linux_sparc/vm/os_linux_sparc.cpp @@ -752,3 +752,8 @@ size_t os::Linux::default_guard_size(os::ThreadType thr_type) { void os::verify_stack_alignment() { } #endif + +int os::extra_bang_size_in_bytes() { + // SPARC does not require the additional stack bang. + return 0; +} diff --git a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp index 3c8e18eef48..136d8066dd4 100644 --- a/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp +++ b/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp @@ -930,3 +930,8 @@ void os::workaround_expand_exec_shield_cs_limit() { // keep the page mapped so CS limit isn't reduced. #endif } + +int os::extra_bang_size_in_bytes() { + // JDK-8050147 requires the full cache line bang for x86. + return VM_Version::L1_line_size(); +} diff --git a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp index f5f44e0a77b..44f7039fa44 100644 --- a/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp +++ b/hotspot/src/os_cpu/linux_zero/vm/os_linux_zero.cpp @@ -495,3 +495,8 @@ extern "C" { void os::verify_stack_alignment() { } #endif + +int os::extra_bang_size_in_bytes() { + // Zero does not require an additional stack banging. + return 0; +} diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp index f22bdcb923e..2f5cd82d66b 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/os_solaris_sparc.cpp @@ -774,3 +774,8 @@ add_func_t* os::atomic_add_func = os::atomic_add_bootstrap; void os::verify_stack_alignment() { } #endif + +int os::extra_bang_size_in_bytes() { + // SPARC does not require an additional stack bang. + return 0; +} diff --git a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp index f30ad48669a..20bac5061ee 100644 --- a/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp +++ b/hotspot/src/os_cpu/solaris_sparc/vm/vm_version_solaris_sparc.cpp @@ -28,10 +28,140 @@ #include "runtime/os.hpp" #include "vm_version_sparc.hpp" -# include -# include -# include -# include +#include +#include +#include +#include +#include + +extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result); +extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result); + +class PICL { + // Get a value of the integer property. The value in the tree can be either 32 or 64 bit + // depending on the platform. The result is converted to int. + static int get_int_property(picl_nodehdl_t nodeh, const char* name, int* result) { + picl_propinfo_t pinfo; + picl_prophdl_t proph; + if (picl_get_prop_by_name(nodeh, name, &proph) != PICL_SUCCESS || + picl_get_propinfo(proph, &pinfo) != PICL_SUCCESS) { + return PICL_FAILURE; + } + + if (pinfo.type != PICL_PTYPE_INT && pinfo.type != PICL_PTYPE_UNSIGNED_INT) { + assert(false, "Invalid property type"); + return PICL_FAILURE; + } + if (pinfo.size == sizeof(int64_t)) { + int64_t val; + if (picl_get_propval(proph, &val, sizeof(int64_t)) != PICL_SUCCESS) { + return PICL_FAILURE; + } + *result = static_cast(val); + } else if (pinfo.size == sizeof(int32_t)) { + int32_t val; + if (picl_get_propval(proph, &val, sizeof(int32_t)) != PICL_SUCCESS) { + return PICL_FAILURE; + } + *result = static_cast(val); + } else { + assert(false, "Unexpected integer property size"); + return PICL_FAILURE; + } + return PICL_SUCCESS; + } + + // Visitor and a state machine that visits integer properties and verifies that the + // values are the same. Stores the unique value observed. + class UniqueValueVisitor { + enum { + INITIAL, // Start state, no assignments happened + ASSIGNED, // Assigned a value + INCONSISTENT // Inconsistent value seen + } _state; + int _value; + public: + UniqueValueVisitor() : _state(INITIAL) { } + int value() { + assert(_state == ASSIGNED, "Precondition"); + return _value; + } + void set_value(int value) { + assert(_state == INITIAL, "Precondition"); + _value = value; + _state = ASSIGNED; + } + bool is_initial() { return _state == INITIAL; } + bool is_assigned() { return _state == ASSIGNED; } + bool is_inconsistent() { return _state == INCONSISTENT; } + void set_inconsistent() { _state = INCONSISTENT; } + + static int visit(picl_nodehdl_t nodeh, const char* name, void *arg) { + UniqueValueVisitor *state = static_cast(arg); + assert(!state->is_inconsistent(), "Precondition"); + int curr; + if (PICL::get_int_property(nodeh, name, &curr) == PICL_SUCCESS) { + if (!state->is_assigned()) { // first iteration + state->set_value(curr); + } else if (curr != state->value()) { // following iterations + state->set_inconsistent(); + } + } + if (state->is_inconsistent()) { + return PICL_WALK_TERMINATE; + } + return PICL_WALK_CONTINUE; + } + }; + + int _L1_data_cache_line_size; + int _L2_cache_line_size; +public: + static int get_l1_data_cache_line_size(picl_nodehdl_t nodeh, void *state) { + return UniqueValueVisitor::visit(nodeh, "l1-dcache-line-size", state); + } + static int get_l2_cache_line_size(picl_nodehdl_t nodeh, void *state) { + return UniqueValueVisitor::visit(nodeh, "l2-cache-line-size", state); + } + + PICL() : _L1_data_cache_line_size(0), _L2_cache_line_size(0) { + if (picl_initialize() == PICL_SUCCESS) { + picl_nodehdl_t rooth; + if (picl_get_root(&rooth) == PICL_SUCCESS) { + UniqueValueVisitor L1_state; + // Visit all "cpu" class instances + picl_walk_tree_by_class(rooth, "cpu", &L1_state, PICL_get_l1_data_cache_line_size_helper); + if (L1_state.is_initial()) { // Still initial, iteration found no values + // Try walk all "core" class instances, it might be a Fujitsu machine + picl_walk_tree_by_class(rooth, "core", &L1_state, PICL_get_l1_data_cache_line_size_helper); + } + if (L1_state.is_assigned()) { // Is there a value? + _L1_data_cache_line_size = L1_state.value(); + } + + UniqueValueVisitor L2_state; + picl_walk_tree_by_class(rooth, "cpu", &L2_state, PICL_get_l2_cache_line_size_helper); + if (L2_state.is_initial()) { + picl_walk_tree_by_class(rooth, "core", &L2_state, PICL_get_l2_cache_line_size_helper); + } + if (L2_state.is_assigned()) { + _L2_cache_line_size = L2_state.value(); + } + } + picl_shutdown(); + } + } + + unsigned int L1_data_cache_line_size() const { return _L1_data_cache_line_size; } + unsigned int L2_cache_line_size() const { return _L2_cache_line_size; } +}; + +extern "C" static int PICL_get_l1_data_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) { + return PICL::get_l1_data_cache_line_size(nodeh, result); +} +extern "C" static int PICL_get_l2_cache_line_size_helper(picl_nodehdl_t nodeh, void *result) { + return PICL::get_l2_cache_line_size(nodeh, result); +} // We need to keep these here as long as we have to build on Solaris // versions before 10. @@ -211,5 +341,10 @@ int VM_Version::platform_features(int features) { kstat_close(kc); } + // Figure out cache line sizes using PICL + PICL picl; + _L1_data_cache_line_size = picl.L1_data_cache_line_size(); + _L2_cache_line_size = picl.L2_cache_line_size(); + return features; } diff --git a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp index 7eccbe47013..5b617a3cbce 100644 --- a/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp +++ b/hotspot/src/os_cpu/solaris_x86/vm/os_solaris_x86.cpp @@ -918,3 +918,8 @@ void os::verify_stack_alignment() { #endif } #endif + +int os::extra_bang_size_in_bytes() { + // JDK-8050147 requires the full cache line bang for x86. + return VM_Version::L1_line_size(); +} diff --git a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp index 6178f1988e5..5325e0ee807 100644 --- a/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp +++ b/hotspot/src/os_cpu/windows_x86/vm/os_windows_x86.cpp @@ -639,3 +639,8 @@ void os::verify_stack_alignment() { #endif } #endif + +int os::extra_bang_size_in_bytes() { + // JDK-8050147 requires the full cache line bang for x86. + return VM_Version::L1_line_size(); +} diff --git a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp index f2753cbff9d..dc43a87389d 100644 --- a/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp +++ b/hotspot/src/share/vm/c1/c1_LIRAssembler.cpp @@ -170,7 +170,7 @@ address LIR_Assembler::pc() const { // removes the need to bang the stack in the deoptimization blob which // in turn simplifies stack overflow handling. int LIR_Assembler::bang_size_in_bytes() const { - return MAX2(initial_frame_size_in_bytes(), _compilation->interpreter_frame_size()); + return MAX2(initial_frame_size_in_bytes() + os::extra_bang_size_in_bytes(), _compilation->interpreter_frame_size()); } void LIR_Assembler::emit_exception_entries(ExceptionInfoList* info_list) { diff --git a/hotspot/src/share/vm/ci/ciEnv.cpp b/hotspot/src/share/vm/ci/ciEnv.cpp index 5353a61964d..f8bb113abae 100644 --- a/hotspot/src/share/vm/ci/ciEnv.cpp +++ b/hotspot/src/share/vm/ci/ciEnv.cpp @@ -926,7 +926,7 @@ void ciEnv::validate_compile_task_dependencies(ciMethod* target) { #ifdef ASSERT if (!counter_changed && !PrintCompilation) { // Print out the compile task that failed - _task->print_line(); + _task->print_tty(); } #endif assert(counter_changed, "failed dependencies, but counter didn't change"); diff --git a/hotspot/src/share/vm/classfile/classLoader.cpp b/hotspot/src/share/vm/classfile/classLoader.cpp index 5eab1812576..ada7857a434 100644 --- a/hotspot/src/share/vm/classfile/classLoader.cpp +++ b/hotspot/src/share/vm/classfile/classLoader.cpp @@ -1528,7 +1528,7 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { if (TieredCompilation && TieredStopAtLevel >= CompLevel_full_optimization) { // Clobber the first compile and force second tier compilation nmethod* nm = m->code(); - if (nm != NULL) { + if (nm != NULL && !m->is_method_handle_intrinsic()) { // Throw out the code so that the code cache doesn't fill up nm->make_not_entrant(); m->clear_code(); @@ -1547,7 +1547,7 @@ void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) { } nmethod* nm = m->code(); - if (nm != NULL) { + if (nm != NULL && !m->is_method_handle_intrinsic()) { // Throw out the code so that the code cache doesn't fill up nm->make_not_entrant(); m->clear_code(); diff --git a/hotspot/src/share/vm/classfile/systemDictionary.cpp b/hotspot/src/share/vm/classfile/systemDictionary.cpp index 6f865acd431..b60e6fa4089 100644 --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp @@ -52,6 +52,7 @@ #include "oops/typeArrayKlass.hpp" #include "prims/jvmtiEnvBase.hpp" #include "prims/methodHandles.hpp" +#include "runtime/arguments.hpp" #include "runtime/biasedLocking.hpp" #include "runtime/fieldType.hpp" #include "runtime/handles.inline.hpp" @@ -2274,7 +2275,11 @@ methodHandle SystemDictionary::find_method_handle_intrinsic(vmIntrinsics::ID iid m = Method::make_method_handle_intrinsic(iid, signature, CHECK_(empty)); CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_highest_tier, methodHandle(), CompileThreshold, "MH", CHECK_(empty)); - + // Check if we need to have compiled code but we don't. + if (!Arguments::is_interpreter_only() && !m->has_compiled_code()) { + THROW_MSG_(vmSymbols::java_lang_VirtualMachineError(), + "out of space in CodeCache for method handle intrinsic", empty); + } // Now grab the lock. We might have to throw away the new method, // if a racing thread has managed to install one at the same time. { @@ -2288,6 +2293,9 @@ methodHandle SystemDictionary::find_method_handle_intrinsic(vmIntrinsics::ID iid } assert(spe != NULL && spe->method() != NULL, ""); + assert(Arguments::is_interpreter_only() || (spe->method()->has_compiled_code() && + spe->method()->code()->entry_point() == spe->method()->from_compiled_entry()), + "MH intrinsic invariant"); return spe->method(); } diff --git a/hotspot/src/share/vm/code/codeCache.cpp b/hotspot/src/share/vm/code/codeCache.cpp index 9cdc302bf78..08ad4e550e3 100644 --- a/hotspot/src/share/vm/code/codeCache.cpp +++ b/hotspot/src/share/vm/code/codeCache.cpp @@ -249,6 +249,7 @@ void CodeCache::commit(CodeBlob* cb) { #define FOR_ALL_BLOBS(var) for (CodeBlob *var = first() ; var != NULL; var = next(var) ) #define FOR_ALL_ALIVE_BLOBS(var) for (CodeBlob *var = alive(first()); var != NULL; var = alive(next(var))) #define FOR_ALL_ALIVE_NMETHODS(var) for (nmethod *var = alive_nmethod(first()); var != NULL; var = alive_nmethod(next(var))) +#define FOR_ALL_NMETHODS(var) for (nmethod *var = first_nmethod(); var != NULL; var = next_nmethod(var)) bool CodeCache::contains(void *p) { @@ -687,7 +688,9 @@ int CodeCache::mark_for_evol_deoptimization(instanceKlassHandle dependee) { void CodeCache::mark_all_nmethods_for_deoptimization() { MutexLockerEx mu(CodeCache_lock, Mutex::_no_safepoint_check_flag); FOR_ALL_ALIVE_NMETHODS(nm) { - nm->mark_for_deoptimization(); + if (!nm->method()->is_method_handle_intrinsic()) { + nm->mark_for_deoptimization(); + } } } @@ -967,6 +970,25 @@ void CodeCache::print_summary(outputStream* st, bool detailed) { } } +void CodeCache::print_codelist(outputStream* st) { + assert_locked_or_safepoint(CodeCache_lock); + + FOR_ALL_NMETHODS(p) { + ResourceMark rm; + char *method_name = p->method()->name_and_sig_as_C_string(); + st->print_cr("%d %d %s ["INTPTR_FORMAT", "INTPTR_FORMAT" - "INTPTR_FORMAT"]", + p->compile_id(), p->comp_level(), method_name, (intptr_t)p->header_begin(), + (intptr_t)p->code_begin(), (intptr_t)p->code_end()); + } +} + +void CodeCache::print_layout(outputStream* st) { + assert_locked_or_safepoint(CodeCache_lock); + ResourceMark rm; + + print_summary(st, true); +} + void CodeCache::log_state(outputStream* st) { st->print(" total_blobs='" UINT32_FORMAT "' nmethods='" UINT32_FORMAT "'" " adapters='" UINT32_FORMAT "' free_code_cache='" SIZE_FORMAT "'", diff --git a/hotspot/src/share/vm/code/codeCache.hpp b/hotspot/src/share/vm/code/codeCache.hpp index 9bd75bfd97d..c117435e891 100644 --- a/hotspot/src/share/vm/code/codeCache.hpp +++ b/hotspot/src/share/vm/code/codeCache.hpp @@ -152,6 +152,10 @@ class CodeCache : AllStatic { static void print_summary(outputStream* st, bool detailed = true); // Prints a summary of the code cache usage static void log_state(outputStream* st); + // Dcmd (Diagnostic commands) + static void print_codelist(outputStream* st); + static void print_layout(outputStream* st); + // The full limits of the codeCache static address low_bound() { return (address) _heap->low_boundary(); } static address high_bound() { return (address) _heap->high_boundary(); } diff --git a/hotspot/src/share/vm/code/compiledIC.cpp b/hotspot/src/share/vm/code/compiledIC.cpp index 25ef072b128..77e435e470f 100644 --- a/hotspot/src/share/vm/code/compiledIC.cpp +++ b/hotspot/src/share/vm/code/compiledIC.cpp @@ -595,6 +595,7 @@ void CompiledStaticCall::compute_entry(methodHandle m, StaticCallInfo& info) { } else { // Callee is interpreted code. In any case entering the interpreter // puts a converter-frame on the stack to save arguments. + assert(!m->is_method_handle_intrinsic(), "Compiled code should never call interpreter MH intrinsics"); info._to_interpreter = true; info._entry = m()->get_c2i_entry(); } diff --git a/hotspot/src/share/vm/code/nmethod.hpp b/hotspot/src/share/vm/code/nmethod.hpp index 10fe4d8e575..d3ed6ae2143 100644 --- a/hotspot/src/share/vm/code/nmethod.hpp +++ b/hotspot/src/share/vm/code/nmethod.hpp @@ -448,7 +448,10 @@ class nmethod : public CodeBlob { // alive. It is used when an uncommon trap happens. Returns true // if this thread changed the state of the nmethod or false if // another thread performed the transition. - bool make_not_entrant() { return make_not_entrant_or_zombie(not_entrant); } + bool make_not_entrant() { + assert(!method()->is_method_handle_intrinsic(), "Cannot make MH intrinsic not entrant"); + return make_not_entrant_or_zombie(not_entrant); + } bool make_zombie() { return make_not_entrant_or_zombie(zombie); } // used by jvmti to track if the unload event has been reported diff --git a/hotspot/src/share/vm/compiler/compileBroker.cpp b/hotspot/src/share/vm/compiler/compileBroker.cpp index 37098b1f4e6..6456bb1d018 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.cpp +++ b/hotspot/src/share/vm/compiler/compileBroker.cpp @@ -166,7 +166,7 @@ class CompilationLog : public StringEventLog { StringLogMessage lm; stringStream sstr = lm.stream(); // msg.time_stamp().update_to(tty->time_stamp().ticks()); - task->print_compilation(&sstr, NULL, true); + task->print_compilation(&sstr, NULL, true, false); log(thread, "%s", (const char*)lm); } @@ -328,7 +328,6 @@ void CompileTask::set_code(nmethod* nm) { if (nm == NULL) _code_handle = NULL; // drop the handle also } - void CompileTask::mark_on_stack() { // Mark these methods as something redefine classes cannot remove. _method->set_on_stack(true); @@ -337,18 +336,6 @@ void CompileTask::mark_on_stack() { } } -// ------------------------------------------------------------------ -// CompileTask::print -void CompileTask::print() { - tty->print("print("method="); - _method->print_name(tty); - tty->print_cr(" osr_bci=%d is_blocking=%s is_complete=%s is_success=%s>", - _osr_bci, bool_to_str(_is_blocking), - bool_to_str(_is_complete), bool_to_str(_is_success)); -} - - // ------------------------------------------------------------------ // CompileTask::print_line_on_error // @@ -367,19 +354,18 @@ void CompileTask::print_line_on_error(outputStream* st, char* buf, int buflen) { // ------------------------------------------------------------------ // CompileTask::print_line -void CompileTask::print_line() { +void CompileTask::print_tty() { ttyLocker ttyl; // keep the following output all in one block // print compiler name if requested if (CIPrintCompilerName) tty->print("%s:", CompileBroker::compiler_name(comp_level())); - print_compilation(); + print_compilation(tty); } - // ------------------------------------------------------------------ // CompileTask::print_compilation_impl void CompileTask::print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level, bool is_osr_method, int osr_bci, bool is_blocking, - const char* msg, bool short_form) { + const char* msg, bool short_form, bool cr) { if (!short_form) { st->print("%7d ", (int) st->time_stamp().milliseconds()); // print timestamp } @@ -428,7 +414,7 @@ void CompileTask::print_compilation_impl(outputStream* st, Method* method, int c if (msg != NULL) { st->print(" %s", msg); } - if (!short_form) { + if (cr) { st->cr(); } } @@ -494,9 +480,9 @@ void CompileTask::print_inline_indent(int inline_level, outputStream* st) { // ------------------------------------------------------------------ // CompileTask::print_compilation -void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form) { +void CompileTask::print_compilation(outputStream* st, const char* msg, bool short_form, bool cr) { bool is_osr_method = osr_bci() != InvocationEntryBci; - print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form); + print_compilation_impl(st, method(), compile_id(), comp_level(), is_osr_method, osr_bci(), is_blocking(), msg, short_form, cr); } // ------------------------------------------------------------------ @@ -621,7 +607,9 @@ void CompileQueue::add(CompileTask* task) { // Mark the method as being in the compile queue. task->method()->set_queued_for_compilation(); - NOT_PRODUCT(print();) + if (CIPrintCompileQueue) { + print_tty(); + } if (LogCompilation && xtty != NULL) { task->log_task_queued(); @@ -786,24 +774,40 @@ void CompileQueue::mark_on_stack() { } } -#ifndef PRODUCT -/** - * Print entire compilation queue. - */ -void CompileQueue::print() { - if (CIPrintCompileQueue) { - ttyLocker ttyl; - tty->print_cr("Contents of %s", name()); - tty->print_cr("----------------------"); - CompileTask* task = _first; + +CompileQueue* CompileBroker::compile_queue(int comp_level) { + if (is_c2_compile(comp_level)) return _c2_compile_queue; + if (is_c1_compile(comp_level)) return _c1_compile_queue; + return NULL; +} + + +void CompileBroker::print_compile_queues(outputStream* st) { + _c1_compile_queue->print(st); + _c2_compile_queue->print(st); +} + + +void CompileQueue::print(outputStream* st) { + assert_locked_or_safepoint(lock()); + st->print_cr("Contents of %s", name()); + st->print_cr("----------------------------"); + CompileTask* task = _first; + if (task == NULL) { + st->print_cr("Empty");; + } else { while (task != NULL) { - task->print_line(); + task->print_compilation(st, NULL, true, true); task = task->next(); } - tty->print_cr("----------------------"); } + st->print_cr("----------------------------"); +} + +void CompileQueue::print_tty() { + ttyLocker ttyl; + print(tty); } -#endif // PRODUCT CompilerCounters::CompilerCounters(const char* thread_name, int instance, TRAPS) { @@ -1068,11 +1072,11 @@ void CompileBroker::init_compiler_threads(int c1_compiler_count, int c2_compiler #endif // !ZERO && !SHARK // Initialize the compilation queue if (c2_compiler_count > 0) { - _c2_compile_queue = new CompileQueue("C2 CompileQueue", MethodCompileQueue_lock); + _c2_compile_queue = new CompileQueue("C2 compile queue", MethodCompileQueue_lock); _compilers[1]->set_num_compiler_threads(c2_compiler_count); } if (c1_compiler_count > 0) { - _c1_compile_queue = new CompileQueue("C1 CompileQueue", MethodCompileQueue_lock); + _c1_compile_queue = new CompileQueue("C1 compile queue", MethodCompileQueue_lock); _compilers[0]->set_num_compiler_threads(c1_compiler_count); } @@ -1892,7 +1896,7 @@ static void codecache_print(bool detailed) void CompileBroker::invoke_compiler_on_method(CompileTask* task) { if (PrintCompilation) { ResourceMark rm; - task->print_line(); + task->print_tty(); } elapsedTimer time; diff --git a/hotspot/src/share/vm/compiler/compileBroker.hpp b/hotspot/src/share/vm/compiler/compileBroker.hpp index 7a381cd3add..466d1eb4d09 100644 --- a/hotspot/src/share/vm/compiler/compileBroker.hpp +++ b/hotspot/src/share/vm/compiler/compileBroker.hpp @@ -111,14 +111,14 @@ class CompileTask : public CHeapObj { private: static void print_compilation_impl(outputStream* st, Method* method, int compile_id, int comp_level, bool is_osr_method = false, int osr_bci = -1, bool is_blocking = false, - const char* msg = NULL, bool short_form = false); + const char* msg = NULL, bool short_form = false, bool cr = true); public: - void print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false); - static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false) { + void print_compilation(outputStream* st = tty, const char* msg = NULL, bool short_form = false, bool cr = true); + static void print_compilation(outputStream* st, const nmethod* nm, const char* msg = NULL, bool short_form = false, bool cr = true) { print_compilation_impl(st, nm->method(), nm->compile_id(), nm->comp_level(), nm->is_osr_method(), nm->is_osr_method() ? nm->osr_entry_bci() : -1, /*is_blocking*/ false, - msg, short_form); + msg, short_form, cr); } static void print_inlining(outputStream* st, ciMethod* method, int inline_level, int bci, const char* msg = NULL); @@ -131,8 +131,7 @@ public: static void print_inline_indent(int inline_level, outputStream* st = tty); - void print(); - void print_line(); + void print_tty(); void print_line_on_error(outputStream* st, char* buf, int buflen); void log_task(xmlStream* log); @@ -234,7 +233,8 @@ class CompileQueue : public CHeapObj { // Redefine Classes support void mark_on_stack(); void free_all(); - NOT_PRODUCT (void print();) + void print_tty(); + void print(outputStream* st = tty); ~CompileQueue() { assert (is_empty(), " Compile Queue must be empty"); @@ -341,7 +341,7 @@ class CompileBroker: AllStatic { static void init_compiler_threads(int c1_compiler_count, int c2_compiler_count); static bool compilation_is_complete (methodHandle method, int osr_bci, int comp_level); static bool compilation_is_prohibited(methodHandle method, int osr_bci, int comp_level); - static bool is_compile_blocking (); + static bool is_compile_blocking(); static void preload_classes (methodHandle method, TRAPS); static CompileTask* create_compile_task(CompileQueue* queue, @@ -369,11 +369,8 @@ class CompileBroker: AllStatic { int hot_count, const char* comment, Thread* thread); - static CompileQueue* compile_queue(int comp_level) { - if (is_c2_compile(comp_level)) return _c2_compile_queue; - if (is_c1_compile(comp_level)) return _c1_compile_queue; - return NULL; - } + + static CompileQueue* compile_queue(int comp_level); static bool init_compiler_runtime(); static void shutdown_compiler_runtime(AbstractCompiler* comp, CompilerThread* thread); @@ -390,6 +387,7 @@ class CompileBroker: AllStatic { } static bool compilation_is_in_queue(methodHandle method); + static void print_compile_queues(outputStream* st); static int queue_size(int comp_level) { CompileQueue *q = compile_queue(comp_level); return q != NULL ? q->size() : 0; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp index 9d2b7da758f..7f728cd78bb 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.cpp @@ -369,33 +369,45 @@ void G1BlockOffsetArray::alloc_block_work2(HeapWord** threshold_, size_t* index_ #endif } -bool -G1BlockOffsetArray::verify_for_object(HeapWord* obj_start, - size_t word_size) const { - size_t first_card = _array->index_for(obj_start); - size_t last_card = _array->index_for(obj_start + word_size - 1); - if (!_array->is_card_boundary(obj_start)) { - // If the object is not on a card boundary the BOT entry of the - // first card should point to another object so we should not - // check that one. - first_card += 1; - } - for (size_t card = first_card; card <= last_card; card += 1) { - HeapWord* card_addr = _array->address_for_index(card); - HeapWord* block_start = block_start_const(card_addr); - if (block_start != obj_start) { - gclog_or_tty->print_cr("block start: "PTR_FORMAT" is incorrect - " - "card index: "SIZE_FORMAT" " - "card addr: "PTR_FORMAT" BOT entry: %u " - "obj: "PTR_FORMAT" word size: "SIZE_FORMAT" " - "cards: ["SIZE_FORMAT","SIZE_FORMAT"]", - p2i(block_start), card, p2i(card_addr), - _array->offset_array(card), - p2i(obj_start), word_size, first_card, last_card); - return false; +void G1BlockOffsetArray::verify() const { + assert(gsp()->bottom() < gsp()->top(), "Only non-empty regions should be verified."); + size_t start_card = _array->index_for(gsp()->bottom()); + size_t end_card = _array->index_for(gsp()->top() - 1); + + for (size_t current_card = start_card; current_card < end_card; current_card++) { + u_char entry = _array->offset_array(current_card); + if (entry < N_words) { + // The entry should point to an object before the current card. Verify that + // it is possible to walk from that object in to the current card by just + // iterating over the objects following it. + HeapWord* card_address = _array->address_for_index(current_card); + HeapWord* obj_end = card_address - entry; + while (obj_end < card_address) { + HeapWord* obj = obj_end; + size_t obj_size = block_size(obj); + obj_end = obj + obj_size; + guarantee(obj_end > obj && obj_end <= gsp()->top(), + err_msg("Invalid object end. obj: " PTR_FORMAT " obj_size: " SIZE_FORMAT " obj_end: " PTR_FORMAT " top: " PTR_FORMAT, + p2i(obj), obj_size, p2i(obj_end), p2i(gsp()->top()))); + } + } else { + // Because we refine the BOT based on which cards are dirty there is not much we can verify here. + // We need to make sure that we are going backwards and that we don't pass the start of the + // corresponding heap region. But that is about all we can verify. + size_t backskip = BlockOffsetArray::entry_to_cards_back(entry); + guarantee(backskip >= 1, "Must be going back at least one card."); + + size_t max_backskip = current_card - start_card; + guarantee(backskip <= max_backskip, + err_msg("Going backwards beyond the start_card. start_card: " SIZE_FORMAT " current_card: " SIZE_FORMAT " backskip: " SIZE_FORMAT, + start_card, current_card, backskip)); + + HeapWord* backskip_address = _array->address_for_index(current_card - backskip); + guarantee(backskip_address >= gsp()->bottom(), + err_msg("Going backwards beyond bottom of the region: bottom: " PTR_FORMAT ", backskip_address: " PTR_FORMAT, + p2i(gsp()->bottom()), p2i(backskip_address))); } } - return true; } #ifndef PRODUCT diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp index 47bcf656857..427e9dce5d2 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1BlockOffsetTable.hpp @@ -304,14 +304,10 @@ public: virtual HeapWord* block_start_unsafe(const void* addr); virtual HeapWord* block_start_unsafe_const(const void* addr) const; - // Used by region verification. Checks that the contents of the - // BOT reflect that there's a single object that spans the address - // range [obj_start, obj_start + word_size); returns true if this is - // the case, returns false if it's not. - bool verify_for_object(HeapWord* obj_start, size_t word_size) const; - void check_all_cards(size_t left_card, size_t right_card) const; + void verify() const; + virtual void print_on(outputStream* out) PRODUCT_RETURN; }; diff --git a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp index 1e75d669d5c..c7cad45fe7d 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/g1CodeCacheRemSet.cpp @@ -48,6 +48,7 @@ class CodeRootSetTable : public Hashtable { return hash ^ (hash >> 7); // code heap blocks are 128byte aligned } + void remove_entry(Entry* e, Entry* previous); Entry* new_entry(nmethod* nm); public: @@ -67,7 +68,7 @@ class CodeRootSetTable : public Hashtable { void nmethods_do(CodeBlobClosure* blk); template - void remove_if(CB& should_remove); + int remove_if(CB& should_remove); static void purge_list_append(CodeRootSetTable* tbl); static void purge(); @@ -91,6 +92,18 @@ CodeRootSetTable::Entry* CodeRootSetTable::new_entry(nmethod* nm) { return entry; } +void CodeRootSetTable::remove_entry(Entry* e, Entry* previous) { + int index = hash_to_index(e->hash()); + assert((e == bucket(index)) == (previous == NULL), "if e is the first entry then previous should be null"); + + if (previous == NULL) { + set_entry(index, e->next()); + } else { + previous->set_next(e->next()); + } + free_entry(e); +} + CodeRootSetTable::~CodeRootSetTable() { for (int index = 0; index < table_size(); ++index) { for (Entry* e = bucket(index); e != NULL; ) { @@ -133,12 +146,7 @@ bool CodeRootSetTable::remove(nmethod* nm) { Entry* previous = NULL; for (Entry* e = bucket(index); e != NULL; previous = e, e = e->next()) { if (e->literal() == nm) { - if (previous != NULL) { - previous->set_next(e->next()); - } else { - set_entry(index, e->next()); - } - free_entry(e); + remove_entry(e, previous); return true; } } @@ -163,25 +171,23 @@ void CodeRootSetTable::nmethods_do(CodeBlobClosure* blk) { } template -void CodeRootSetTable::remove_if(CB& should_remove) { +int CodeRootSetTable::remove_if(CB& should_remove) { + int num_removed = 0; for (int index = 0; index < table_size(); ++index) { Entry* previous = NULL; Entry* e = bucket(index); while (e != NULL) { Entry* next = e->next(); if (should_remove(e->literal())) { - if (previous != NULL) { - previous->set_next(next); - } else { - set_entry(index, next); - } - free_entry(e); + remove_entry(e, previous); + ++num_removed; } else { previous = e; } e = next; } } + return num_removed; } G1CodeRootSet::~G1CodeRootSet() { @@ -320,14 +326,19 @@ class CleanCallback : public StackObj { bool operator() (nmethod* nm) { _detector._points_into = false; _blobs.do_code_blob(nm); - return _detector._points_into; + return !_detector._points_into; } }; void G1CodeRootSet::clean(HeapRegion* owner) { CleanCallback should_clean(owner); if (_table != NULL) { - _table->remove_if(should_clean); + int removed = _table->remove_if(should_clean); + assert((size_t)removed <= _length, "impossible"); + _length -= removed; + } + if (_length == 0) { + clear(); } } diff --git a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp index aa6697a742c..0c7c3906cb3 100644 --- a/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp +++ b/hotspot/src/share/vm/gc_implementation/g1/heapRegion.cpp @@ -861,7 +861,6 @@ void HeapRegion::verify(VerifyOption vo, HeapWord* prev_p = NULL; VerifyLiveClosure vl_cl(g1, vo); bool is_humongous = isHumongous(); - bool do_bot_verify = !is_young(); size_t object_num = 0; while (p < top()) { oop obj = oop(p); @@ -878,15 +877,6 @@ void HeapRegion::verify(VerifyOption vo, return; } - // If it returns false, verify_for_object() will output the - // appropriate message. - if (do_bot_verify && - !g1->is_obj_dead(obj, this) && - !_offsets.verify_for_object(p, obj_size)) { - *failures = true; - return; - } - if (!g1->is_obj_dead_cond(obj, this, vo)) { if (obj->is_oop()) { Klass* klass = obj->klass(); @@ -924,6 +914,10 @@ void HeapRegion::verify(VerifyOption vo, p += obj_size; } + if (!is_young() && !is_empty()) { + _offsets.verify(); + } + if (p != top()) { gclog_or_tty->print_cr("end of last object "PTR_FORMAT" " "does not match top "PTR_FORMAT, p, top()); diff --git a/hotspot/src/share/vm/oops/method.cpp b/hotspot/src/share/vm/oops/method.cpp index 589d758e38c..fb9af5282d6 100644 --- a/hotspot/src/share/vm/oops/method.cpp +++ b/hotspot/src/share/vm/oops/method.cpp @@ -1635,34 +1635,34 @@ int Method::backedge_count() { } int Method::highest_comp_level() const { - const MethodData* mdo = method_data(); - if (mdo != NULL) { - return mdo->highest_comp_level(); + const MethodCounters* mcs = method_counters(); + if (mcs != NULL) { + return mcs->highest_comp_level(); } else { return CompLevel_none; } } int Method::highest_osr_comp_level() const { - const MethodData* mdo = method_data(); - if (mdo != NULL) { - return mdo->highest_osr_comp_level(); + const MethodCounters* mcs = method_counters(); + if (mcs != NULL) { + return mcs->highest_osr_comp_level(); } else { return CompLevel_none; } } void Method::set_highest_comp_level(int level) { - MethodData* mdo = method_data(); - if (mdo != NULL) { - mdo->set_highest_comp_level(level); + MethodCounters* mcs = method_counters(); + if (mcs != NULL) { + mcs->set_highest_comp_level(level); } } void Method::set_highest_osr_comp_level(int level) { - MethodData* mdo = method_data(); - if (mdo != NULL) { - mdo->set_highest_osr_comp_level(level); + MethodCounters* mcs = method_counters(); + if (mcs != NULL) { + mcs->set_highest_osr_comp_level(level); } } diff --git a/hotspot/src/share/vm/oops/methodCounters.cpp b/hotspot/src/share/vm/oops/methodCounters.cpp index 91b05a7bcc8..25379d25658 100644 --- a/hotspot/src/share/vm/oops/methodCounters.cpp +++ b/hotspot/src/share/vm/oops/methodCounters.cpp @@ -35,4 +35,40 @@ void MethodCounters::clear_counters() { set_interpreter_throwout_count(0); set_interpreter_invocation_count(0); set_nmethod_age(INT_MAX); +#ifdef TIERED + set_prev_time(0); + set_rate(0); + set_highest_comp_level(0); + set_highest_osr_comp_level(0); +#endif } + + +int MethodCounters::highest_comp_level() const { +#ifdef TIERED + return _highest_comp_level; +#else + return CompLevel_none; +#endif +} + +void MethodCounters::set_highest_comp_level(int level) { +#ifdef TIERED + _highest_comp_level = level; +#endif +} + +int MethodCounters::highest_osr_comp_level() const { +#ifdef TIERED + return _highest_osr_comp_level; +#else + return CompLevel_none; +#endif +} + +void MethodCounters::set_highest_osr_comp_level(int level) { +#ifdef TIERED + _highest_osr_comp_level = level; +#endif +} + diff --git a/hotspot/src/share/vm/oops/methodCounters.hpp b/hotspot/src/share/vm/oops/methodCounters.hpp index 75b8c9e6e16..a21d376b871 100644 --- a/hotspot/src/share/vm/oops/methodCounters.hpp +++ b/hotspot/src/share/vm/oops/methodCounters.hpp @@ -49,6 +49,8 @@ class MethodCounters: public MetaspaceObj { #ifdef TIERED float _rate; // Events (invocation and backedge counter increments) per millisecond jlong _prev_time; // Previous time the rate was acquired + u1 _highest_comp_level; // Highest compile level this method has ever seen. + u1 _highest_osr_comp_level; // Same for OSR level #endif MethodCounters() : _interpreter_invocation_count(0), @@ -57,7 +59,9 @@ class MethodCounters: public MetaspaceObj { _nmethod_age(INT_MAX) #ifdef TIERED , _rate(0), - _prev_time(0) + _prev_time(0), + _highest_comp_level(0), + _highest_osr_comp_level(0) #endif { invocation_counter()->init(); @@ -114,6 +118,11 @@ class MethodCounters: public MetaspaceObj { void set_rate(float rate) { _rate = rate; } #endif + int highest_comp_level() const; + void set_highest_comp_level(int level); + int highest_osr_comp_level() const; + void set_highest_osr_comp_level(int level); + // invocation counter InvocationCounter* invocation_counter() { return &_invocation_counter; } InvocationCounter* backedge_counter() { return &_backedge_counter; } diff --git a/hotspot/src/share/vm/oops/methodData.cpp b/hotspot/src/share/vm/oops/methodData.cpp index fdf8c7fd112..95fdb621301 100644 --- a/hotspot/src/share/vm/oops/methodData.cpp +++ b/hotspot/src/share/vm/oops/methodData.cpp @@ -1134,8 +1134,6 @@ void MethodData::init() { _tenure_traps = 0; _num_loops = 0; _num_blocks = 0; - _highest_comp_level = 0; - _highest_osr_comp_level = 0; _would_profile = true; #if INCLUDE_RTM_OPT diff --git a/hotspot/src/share/vm/oops/methodData.hpp b/hotspot/src/share/vm/oops/methodData.hpp index edb82ae9ddb..cd273f50bad 100644 --- a/hotspot/src/share/vm/oops/methodData.hpp +++ b/hotspot/src/share/vm/oops/methodData.hpp @@ -2095,10 +2095,6 @@ private: // time with C1. It is used to determine if method is trivial. short _num_loops; short _num_blocks; - // Highest compile level this method has ever seen. - u1 _highest_comp_level; - // Same for OSR level - u1 _highest_osr_comp_level; // Does this method contain anything worth profiling? bool _would_profile; @@ -2277,11 +2273,6 @@ public: void set_would_profile(bool p) { _would_profile = p; } bool would_profile() const { return _would_profile; } - int highest_comp_level() const { return _highest_comp_level; } - void set_highest_comp_level(int level) { _highest_comp_level = level; } - int highest_osr_comp_level() const { return _highest_osr_comp_level; } - void set_highest_osr_comp_level(int level) { _highest_osr_comp_level = level; } - int num_loops() const { return _num_loops; } void set_num_loops(int n) { _num_loops = n; } int num_blocks() const { return _num_blocks; } diff --git a/hotspot/src/share/vm/opto/compile.cpp b/hotspot/src/share/vm/opto/compile.cpp index a70e538d744..3d88cfc616b 100644 --- a/hotspot/src/share/vm/opto/compile.cpp +++ b/hotspot/src/share/vm/opto/compile.cpp @@ -430,7 +430,7 @@ int Compile::frame_size_in_words() const { // removes the need to bang the stack in the deoptimization blob which // in turn simplifies stack overflow handling. int Compile::bang_size_in_bytes() const { - return MAX2(_interpreter_frame_size, frame_size_in_bytes()); + return MAX2(frame_size_in_bytes() + os::extra_bang_size_in_bytes(), _interpreter_frame_size); } // ============================================================================ diff --git a/hotspot/src/share/vm/opto/library_call.cpp b/hotspot/src/share/vm/opto/library_call.cpp index 9f60b701469..a59007b7ccc 100644 --- a/hotspot/src/share/vm/opto/library_call.cpp +++ b/hotspot/src/share/vm/opto/library_call.cpp @@ -4968,7 +4968,8 @@ bool LibraryCallKit::inline_multiplyToLen() { // Allocate the result array Node* zlen = _gvn.transform(new AddINode(xlen, ylen)); - Node* klass_node = makecon(TypeKlassPtr::make(ciTypeArrayKlass::make(T_INT))); + ciKlass* klass = ciTypeArrayKlass::make(T_INT); + Node* klass_node = makecon(TypeKlassPtr::make(klass)); IdealKit ideal(this); @@ -5002,7 +5003,8 @@ bool LibraryCallKit::inline_multiplyToLen() { sync_kit(ideal); z = __ value(z_alloc); - _gvn.set_type(z, TypeAryPtr::INTS); + // Can't use TypeAryPtr::INTS which uses Bottom offset. + _gvn.set_type(z, TypeOopPtr::make_from_klass(klass)); // Final sync IdealKit and GraphKit. final_sync(ideal); #undef __ diff --git a/hotspot/src/share/vm/runtime/arguments.hpp b/hotspot/src/share/vm/runtime/arguments.hpp index 28608e2ba1a..72b9d325647 100644 --- a/hotspot/src/share/vm/runtime/arguments.hpp +++ b/hotspot/src/share/vm/runtime/arguments.hpp @@ -590,7 +590,9 @@ class Arguments : AllStatic { static void fix_appclasspath(); // Operation modi - static Mode mode() { return _mode; } + static Mode mode() { return _mode; } + static bool is_interpreter_only() { return mode() == _int; } + // Utility: copies src into buf, replacing "%%" with "%" and "%p" with pid. static bool copy_expand_pid(const char* src, size_t srclen, char* buf, size_t buflen); diff --git a/hotspot/src/share/vm/runtime/globals.hpp b/hotspot/src/share/vm/runtime/globals.hpp index 372f6c720ab..5673ab6ee6c 100644 --- a/hotspot/src/share/vm/runtime/globals.hpp +++ b/hotspot/src/share/vm/runtime/globals.hpp @@ -2473,7 +2473,7 @@ class CommandLineFlags { develop(bool, CIPrintCompilerName, false, \ "when CIPrint is active, print the name of the active compiler") \ \ - develop(bool, CIPrintCompileQueue, false, \ + diagnostic(bool, CIPrintCompileQueue, false, \ "display the contents of the compile queue whenever a " \ "compilation is enqueued") \ \ diff --git a/hotspot/src/share/vm/runtime/os.hpp b/hotspot/src/share/vm/runtime/os.hpp index 64406254ab9..3a4f466ee0b 100644 --- a/hotspot/src/share/vm/runtime/os.hpp +++ b/hotspot/src/share/vm/runtime/os.hpp @@ -772,6 +772,9 @@ class os: AllStatic { // Hook for os specific jvm options that we don't want to abort on seeing static bool obsolete_option(const JavaVMOption *option); + // Amount beyond the callee frame size that we bang the stack. + static int extra_bang_size_in_bytes(); + // Extensions #include "runtime/os_ext.hpp" diff --git a/hotspot/src/share/vm/runtime/sweeper.cpp b/hotspot/src/share/vm/runtime/sweeper.cpp index 0a964ac8728..10ec6ff05dc 100644 --- a/hotspot/src/share/vm/runtime/sweeper.cpp +++ b/hotspot/src/share/vm/runtime/sweeper.cpp @@ -618,7 +618,7 @@ void NMethodSweeper::possibly_flush(nmethod* nm) { if (mc == NULL) { // Sometimes we can get here without MethodCounters. For example if we run with -Xcomp. // Try to allocate them. - mc = Method::build_method_counters(nm->method(), Thread::current()); + mc = nm->method()->get_method_counters(Thread::current()); } if (mc != NULL) { // Snapshot the value as it's changed concurrently diff --git a/hotspot/src/share/vm/runtime/vm_operations.cpp b/hotspot/src/share/vm/runtime/vm_operations.cpp index 2e913c5015f..da07423db81 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.cpp +++ b/hotspot/src/share/vm/runtime/vm_operations.cpp @@ -470,3 +470,15 @@ void VM_Exit::wait_if_vm_exited() { ShouldNotReachHere(); } } + +void VM_PrintCompileQueue::doit() { + CompileBroker::print_compile_queues(_out); +} + +void VM_PrintCodeList::doit() { + CodeCache::print_codelist(_out); +} + +void VM_PrintCodeCache::doit() { + CodeCache::print_layout(_out); +} diff --git a/hotspot/src/share/vm/runtime/vm_operations.hpp b/hotspot/src/share/vm/runtime/vm_operations.hpp index 4e32a3adfa2..ce9c08536db 100644 --- a/hotspot/src/share/vm/runtime/vm_operations.hpp +++ b/hotspot/src/share/vm/runtime/vm_operations.hpp @@ -99,6 +99,9 @@ template(RotateGCLog) \ template(WhiteBoxOperation) \ template(ClassLoaderStatsOperation) \ + template(PrintCompileQueue) \ + template(PrintCodeList) \ + template(PrintCodeCache) \ class VM_Operation: public CHeapObj { public: @@ -413,4 +416,35 @@ class VM_RotateGCLog: public VM_Operation { void doit() { gclog_or_tty->rotate_log(true, _out); } }; +class VM_PrintCompileQueue: public VM_Operation { + private: + outputStream* _out; + + public: + VM_PrintCompileQueue(outputStream* st) : _out(st) {} + VMOp_Type type() const { return VMOp_PrintCompileQueue; } + void doit(); +}; + +class VM_PrintCodeList: public VM_Operation { + private: + outputStream* _out; + + public: + VM_PrintCodeList(outputStream* st) : _out(st) {} + VMOp_Type type() const { return VMOp_PrintCodeList; } + void doit(); +}; + +class VM_PrintCodeCache: public VM_Operation { + private: + outputStream* _out; + + public: + VM_PrintCodeCache(outputStream* st) : _out(st) {} + VMOp_Type type() const { return VMOp_PrintCodeCache; } + void doit(); +}; + + #endif // SHARE_VM_RUNTIME_VM_OPERATIONS_HPP diff --git a/hotspot/src/share/vm/services/diagnosticCommand.cpp b/hotspot/src/share/vm/services/diagnosticCommand.cpp index 892e2ce57b6..8f8309f97f7 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.cpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.cpp @@ -60,6 +60,9 @@ void DCmdRegistrant::register_dcmds(){ DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); // Enhanced JMX Agent Support // These commands won't be exported via the DiagnosticCommandMBean until an @@ -674,3 +677,18 @@ void RotateGCLogDCmd::execute(DCmdSource source, TRAPS) { } } +void CompileQueueDCmd::execute(DCmdSource source, TRAPS) { + VM_PrintCompileQueue printCompileQueueOp(output()); + VMThread::execute(&printCompileQueueOp); +} + +void CodeListDCmd::execute(DCmdSource source, TRAPS) { + VM_PrintCodeList printCodeListOp(output()); + VMThread::execute(&printCodeListOp); +} + +void CodeCacheDCmd::execute(DCmdSource source, TRAPS) { + VM_PrintCodeCache printCodeCacheOp(output()); + VMThread::execute(&printCodeCacheOp); +} + diff --git a/hotspot/src/share/vm/services/diagnosticCommand.hpp b/hotspot/src/share/vm/services/diagnosticCommand.hpp index 73e8673dddb..e87410cfd0b 100644 --- a/hotspot/src/share/vm/services/diagnosticCommand.hpp +++ b/hotspot/src/share/vm/services/diagnosticCommand.hpp @@ -399,4 +399,68 @@ public: } }; +class CompileQueueDCmd : public DCmd { +public: + CompileQueueDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} + static const char* name() { + return "Compiler.queue"; + } + static const char* description() { + return "Print methods queued for compilation."; + } + static const char* impact() { + return "Low"; + } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + static int num_arguments() { return 0; } + virtual void execute(DCmdSource source, TRAPS); +}; + +class CodeListDCmd : public DCmd { +public: + CodeListDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} + static const char* name() { + return "Compiler.codelist"; + } + static const char* description() { + return "Print all compiled methods in code cache."; + } + static const char* impact() { + return "Medium"; + } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + static int num_arguments() { return 0; } + virtual void execute(DCmdSource source, TRAPS); +}; + + +class CodeCacheDCmd : public DCmd { +public: + CodeCacheDCmd(outputStream* output, bool heap) : DCmd(output, heap) {} + static const char* name() { + return "Compiler.codecache"; + } + static const char* description() { + return "Print code cache layout and bounds."; + } + static const char* impact() { + return "Low"; + } + static const JavaPermission permission() { + JavaPermission p = {"java.lang.management.ManagementPermission", + "monitor", NULL}; + return p; + } + static int num_arguments() { return 0; } + virtual void execute(DCmdSource source, TRAPS); +}; + #endif // SHARE_VM_SERVICES_DIAGNOSTICCOMMAND_HPP diff --git a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java index 5d7b60395cd..bf627db8b0e 100644 --- a/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java +++ b/hotspot/test/gc/arguments/TestParallelHeapSizeFlags.java @@ -22,7 +22,7 @@ */ /* - * @ignore 8027915 + * @ignore 8049864 * @test TestParallelHeapSizeFlags * @key gc * @bug 8006088 diff --git a/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java index eb947c13488..0dd5739e835 100644 --- a/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java +++ b/hotspot/test/gc/arguments/TestUseCompressedOopsErgo.java @@ -22,7 +22,6 @@ */ /* - * @ignore 8025645 * @test TestUseCompressedOopsErgo * @key gc * @bug 8010722 diff --git a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java index 7a23509712d..336f7b9939e 100644 --- a/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java +++ b/hotspot/test/gc/parallelScavenge/TestDynShrinkHeap.java @@ -22,7 +22,7 @@ */ /** - * @ignore 8042051 + * @ignore 8019361 * @test TestDynShrinkHeap * @bug 8016479 * @summary Verify that the heap shrinks after full GC according to the current values of the Min/MaxHeapFreeRatio flags diff --git a/hotspot/test/serviceability/dcmd/CodeCacheTest.java b/hotspot/test/serviceability/dcmd/CodeCacheTest.java new file mode 100644 index 00000000000..906403d914b --- /dev/null +++ b/hotspot/test/serviceability/dcmd/CodeCacheTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test CodeCacheTest + * @bug 8054889 + * @build DcmdUtil CodeCacheTest + * @run main CodeCacheTest + * @summary Test of diagnostic command Compiler.codecache + */ + +import java.io.BufferedReader; +import java.io.StringReader; +import java.lang.reflect.Method; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class CodeCacheTest { + + /** + * This test calls Jcmd (diagnostic command tool) Compiler.codecache and then parses the output, + * making sure that all number look ok + * + * + * Expected output: + * + * CodeCache: size=245760Kb used=4680Kb max_used=4680Kb free=241079Kb + * bounds [0x00007f5bd9000000, 0x00007f5bd94a0000, 0x00007f5be8000000] + * total_blobs=575 nmethods=69 adapters=423 + * compilation: enabled + */ + + static Pattern line1 = Pattern.compile("CodeCache: size=(\\p{Digit}*)Kb used=(\\p{Digit}*)Kb max_used=(\\p{Digit}*)Kb free=(\\p{Digit}*)Kb"); + static Pattern line2 = Pattern.compile(" bounds \\[0x(\\p{XDigit}*), 0x(\\p{XDigit}*), 0x(\\p{XDigit}*)\\]"); + static Pattern line3 = Pattern.compile(" total_blobs=(\\p{Digit}*) nmethods=(\\p{Digit}*) adapters=(\\p{Digit}*)"); + static Pattern line4 = Pattern.compile(" compilation: (\\w*)"); + + public static void main(String arg[]) throws Exception { + + // Get output from dcmd (diagnostic command) + String result = DcmdUtil.executeDcmd("Compiler.codecache"); + BufferedReader r = new BufferedReader(new StringReader(result)); + + // Validate first line + String line; + line = r.readLine(); + Matcher m = line1.matcher(line); + if (m.matches()) { + for(int i = 1; i <= 4; i++) { + int val = Integer.parseInt(m.group(i)); + if (val < 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + } + } else { + throw new Exception("Regexp 1 failed"); + } + + // Validate second line + line = r.readLine(); + m = line2.matcher(line); + if (m.matches()) { + long start = Long.parseLong(m.group(1), 16); + if (start < 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + long mark = Long.parseLong(m.group(2), 16); + if (mark < 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + long top = Long.parseLong(m.group(3), 16); + if (top < 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + if (start > mark) { + throw new Exception("Failed parsing dcmd codecache output"); + } + if (mark > top) { + throw new Exception("Failed parsing dcmd codecache output"); + } + } else { + throw new Exception("Regexp 2 failed line: " + line); + } + + // Validate third line + line = r.readLine(); + m = line3.matcher(line); + if (m.matches()) { + int blobs = Integer.parseInt(m.group(1)); + if (blobs <= 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + int nmethods = Integer.parseInt(m.group(2)); + if (nmethods <= 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + int adapters = Integer.parseInt(m.group(3)); + if (adapters <= 0) { + throw new Exception("Failed parsing dcmd codecache output"); + } + if (blobs < (nmethods + adapters)) { + throw new Exception("Failed parsing dcmd codecache output"); + } + } else { + throw new Exception("Regexp 3 failed"); + } + + // Validate fourth line + line = r.readLine(); + m = line4.matcher(line); + if (m.matches()) { + if (!m.group(1).equals("enabled")) { + throw new Exception("Invalid message: '" + m.group(1) + "'"); + } + } else { + throw new Exception("Regexp 4 failed"); + } + } +} diff --git a/hotspot/test/serviceability/dcmd/CodelistTest.java b/hotspot/test/serviceability/dcmd/CodelistTest.java new file mode 100644 index 00000000000..a84ddc82706 --- /dev/null +++ b/hotspot/test/serviceability/dcmd/CodelistTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test CodelistTest + * @bug 8054889 + * @build DcmdUtil MethodIdentifierParser CodelistTest + * @run main CodelistTest + * @summary Test of diagnostic command Compiler.codelist + */ + +import java.io.BufferedReader; +import java.io.StringReader; +import java.lang.reflect.Method; + +public class CodelistTest { + + /** + * This test calls Jcmd (diagnostic command tool) Compiler.codelist and then parses the output, + * making sure that the first methods in the list is valid by reflection. + * + * Output example: + * + * 6 0 java.lang.System.arraycopy(Ljava/lang/Object;ILjava/lang/Object;II)V [0x00007f7b49200910, 0x00007f7b49200aa0 - 0x00007f7b49200d30] + * 2 3 java.lang.String.indexOf(II)I [0x00007f7b49200d90, 0x00007f7b49200f60 - 0x00007f7b49201490] + * 7 3 java.lang.Math.min(II)I [0x00007f7b4922f010, 0x00007f7b4922f180 - 0x00007f7b4922f338] + * 8 3 java.lang.String.equals(Ljava/lang/Object;)Z [0x00007f7b4922fb10, 0x00007f7b4922fd40 - 0x00007f7b49230698] + * 9 3 java.lang.AbstractStringBuilder.ensureCapacityInternal(I)V [0x00007f7b49232010, 0x00007f7b492321a0 - 0x00007f7b49232510] + * 10 1 java.lang.Object.()V [0x00007f7b49233e90, 0x00007f7b49233fe0 - 0x00007f7b49234118] + * + */ + + public static void main(String arg[]) throws Exception { + int ok = 0; + int fail = 0; + + // Get output from dcmd (diagnostic command) + String result = DcmdUtil.executeDcmd("Compiler.codelist"); + BufferedReader r = new BufferedReader(new StringReader(result)); + + // Grab a method name from the output + String line; + int count = 0; + + while((line = r.readLine()) != null) { + count++; + + String[] parts = line.split(" "); + // int compileID = Integer.parseInt(parts[0]); + // int compileLevel = Integer.parseInt(parts[1]); + String methodPrintedInLogFormat = parts[2]; + + // skip inits and clinits - they can not be reflected + if (methodPrintedInLogFormat.contains("")) { + continue; + } + if (methodPrintedInLogFormat.contains("")) { + continue; + } + + MethodIdentifierParser mf = new MethodIdentifierParser(methodPrintedInLogFormat); + Method m; + try { + m = mf.getMethod(); + } catch (NoSuchMethodException e) { + m = null; + } + if (m == null) { + throw new Exception("Test failed"); + } + if (count > 10) { + // Testing 10 entries is enough. Lets not waste time. + break; + } + } + } +} diff --git a/hotspot/test/serviceability/dcmd/CompilerQueueTest.java b/hotspot/test/serviceability/dcmd/CompilerQueueTest.java new file mode 100644 index 00000000000..8120308100f --- /dev/null +++ b/hotspot/test/serviceability/dcmd/CompilerQueueTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test CompilerQueueTest + * @bug 8054889 + * @build DcmdUtil CompilerQueueTest + * @run main CompilerQueueTest + * @summary Test of diagnostic command Compiler.queue + */ + +import java.io.BufferedReader; +import java.io.StringReader; + +public class CompilerQueueTest { + + /** + * This test calls Jcmd (diagnostic command tool) Compiler.queue and + * then parses the output, making sure that the output look ok. + * + * + * Output example: + * + * Contents of C1 compile queue + * ---------------------------- + * 73 3 java.lang.AbstractStringBuilder::append (50 bytes) + * 74 1 java.util.TreeMap::size (5 bytes) + * 75 3 java.lang.StringBuilder::append (8 bytes) + * 83 3 java.util.TreeMap$ValueIterator::next (8 bytes) + * 84 1 javax.management.MBeanFeatureInfo::getName (5 bytes) + * ---------------------------- + * Contents of C2 compile queue + * ---------------------------- + * Empty + * ---------------------------- + * + **/ + + public static void main(String arg[]) throws Exception { + + // Get output from dcmd (diagnostic command) + String result = DcmdUtil.executeDcmd("Compiler.queue"); + BufferedReader r = new BufferedReader(new StringReader(result)); + + String line; + match(r.readLine(), "Contents of C1 compile queue"); + match(r.readLine(), "----------------------------"); + String str = r.readLine(); + if (!str.equals("Empty")) { + while (str.charAt(0) != '-') { + validateMethodLine(str); + str = r.readLine(); + } + } else { + str = r.readLine(); + } + + match(str, "----------------------------"); + match(r.readLine(), "Contents of C2 compile queue"); + match(r.readLine(), "----------------------------"); + str = r.readLine(); + if (!str.equals("Empty")) { + while (str.charAt(0) != '-') { + validateMethodLine(str); + str = r.readLine(); + } + } else { + str = r.readLine(); + } + match(str, "----------------------------"); + } + + private static void validateMethodLine(String str) throws Exception { + String name = str.substring(19); + int sep = name.indexOf("::"); + try { + Class.forName(name.substring(0, sep)); + } catch (ClassNotFoundException e) { + throw new Exception("Failed parsing dcmd queue"); + } + } + + public static void match(String line, String str) throws Exception { + if (!line.equals(str)) { + throw new Exception("String equals: " + line + ", " + str); + } + } +} diff --git a/hotspot/test/serviceability/dcmd/MethodIdentifierParser.java b/hotspot/test/serviceability/dcmd/MethodIdentifierParser.java new file mode 100644 index 00000000000..f00c0dd9863 --- /dev/null +++ b/hotspot/test/serviceability/dcmd/MethodIdentifierParser.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.reflect.Method; +import java.util.ArrayList; + +public class MethodIdentifierParser { + + private String logString; + private String className; + private String methodName; + private String methodDescriptor; + + /** + * This is a utility class for parsing the log entries for a method. It supplies + * a few select methods for reflecting the class and method from that information. + * + * Example log entries: + * "java.util.TreeMap.successor(Ljava/util/TreeMap$Entry;)Ljava/util/TreeMap$Entry;" + */ + + public MethodIdentifierParser(String logString) { + this.logString = logString; + + int i = logString.lastIndexOf("."); // find start of method name + className = logString.substring(0, i); // classname is everything before + int i2 = logString.indexOf("("); // Signature starts with an '(' + methodName = logString.substring(i+1, i2); + methodDescriptor = logString.substring(i2, logString.length()); + + // Add sanity check for extracted fields + } + + public Method getMethod() throws NoSuchMethodException, SecurityException, ClassNotFoundException, Exception { + try { + return Class.forName(className).getDeclaredMethod(methodName, getParamenterDescriptorArray()); + } catch (UnexpectedTokenException e) { + throw new Exception("Parse failed"); + } + } + + public Class[] getParamenterDescriptorArray() throws ClassNotFoundException, UnexpectedTokenException { + ParameterDecriptorIterator s = new ParameterDecriptorIterator(methodDescriptor); + Class paramType; + ArrayList> list = new ArrayList>(); + while ((paramType = s.nextParamType()) != null) { + list.add(paramType); + } + if (list.size() > 0) { + return list.toArray(new Class[list.size()]); + } else { + return null; + } + } + + class ParameterDecriptorIterator { + + // This class uses charAt() indexing for startMark and i + // That is when i points to the last char it can be retrieved with + // charAt(i). Including the last char for a subString requires + // substring(startMark, i+1); + + private String methodDescriptor; + private int startMark; + + public ParameterDecriptorIterator(String signature) { + this.methodDescriptor = signature; + this.startMark = 0; + if (signature.charAt(0) == '(') { + this.startMark = 1; + } + } + + public Class nextParamType() throws UnexpectedTokenException { + int i = startMark; + while (methodDescriptor.length() > i) { + switch (methodDescriptor.charAt(i)) { + case 'C': + case 'B': + case 'I': + case 'J': + case 'Z': + case 'F': + case 'D': + case 'S': + // Primitive class case, but we may have gotten here with [ as first token + break; + case 'L': + // Internal class name suffixed by ';' + while (methodDescriptor.charAt(i) != ';') { + i++; + } + break; + case '[': + i++; // arrays -> do another pass + continue; + case ')': + return null; // end found + case 'V': + case ';': + default: + throw new UnexpectedTokenException(methodDescriptor, i); + } + break; + } + if (i == startMark) { + // Single char -> primitive class case + startMark++; // Update for next iteration + switch (methodDescriptor.charAt(i)) { + case 'C': + return char.class; + case 'B': + return byte.class; + case 'I': + return int.class; + case 'J': + return long.class; + case 'F': + return float.class; + case 'D': + return double.class; + case 'S': + return short.class; + case 'Z': + return boolean.class; + default: + throw new UnexpectedTokenException(methodDescriptor, i); + } + } else { + // Multi char case + String nextParam; + if (methodDescriptor.charAt(startMark) == 'L') { + // When reflecting a class the leading 'L' and trailing';' must be removed. + // (When reflecting an array of classes, they must remain...) + nextParam = methodDescriptor.substring(startMark+1, i); + } else { + // Any kind of array - simple case, use whole descriptor when reflecting. + nextParam = methodDescriptor.substring(startMark, i+1); + } + startMark = ++i; // Update for next iteration + try { + // The parameter descriptor uses JVM internal class identifier with '/' as + // package separator, but Class.forName expects '.'. + nextParam = nextParam.replace('/', '.'); + return Class.forName(nextParam); + } catch (ClassNotFoundException e) { + System.out.println("Class not Found: " + nextParam); + return null; + } + } + } + } + + class UnexpectedTokenException extends Exception { + String descriptor; + int i; + public UnexpectedTokenException(String descriptor, int i) { + this.descriptor = descriptor; + this.i = i; + } + + @Override + public String toString() { + return "Unexpected token at: " + i + " in signature: " + descriptor; + } + + private static final long serialVersionUID = 1L; + } + + public void debugPrint() { + System.out.println("mlf in: " + logString); + System.out.println("mlf class: " + className); + System.out.println("mlf method: " + methodName); + System.out.println("mlf methodDescriptor: " + methodDescriptor); + } +} diff --git a/jaxp/.hgignore b/jaxp/.hgignore index 970fc82946b..195f7dbfed1 100644 --- a/jaxp/.hgignore +++ b/jaxp/.hgignore @@ -2,6 +2,6 @@ ^dist/ ^drop/ ^drop_included/ -^webrev/ +^webrev /nbproject/private/ ^.hgtip diff --git a/jaxp/.hgtags b/jaxp/.hgtags index 051c0879c7b..ea01e6ee220 100644 --- a/jaxp/.hgtags +++ b/jaxp/.hgtags @@ -269,3 +269,7 @@ f9c82769a6bc2b219a8f01c24afe5c91039267d7 jdk9-b19 345af113f57206711f75089c3ebf84a36a789122 jdk9-b24 73757f4b8aa353ca8937abc07e79e7ece4c011a1 jdk9-b25 a5aea8318ae4a9c2105228568688875142d70344 jdk9-b26 +2bfaf29cc90b19948938e3ef1a0983eee68806c7 jdk9-b27 +dc1e26434b3fd7e9b8eeab149103c1e30965f95c jdk9-b28 +30adcd13a313ea91e81164801a2f89282756d933 jdk9-b29 +d181d4002214e4914d5525bd5ee13369311c765c jdk9-b30 diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Constants.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Constants.java index 4e276fb6ad6..3a84797138b 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Constants.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/Constants.java @@ -1,13 +1,10 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - */ - -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -41,6 +38,9 @@ public final class Constants { public static final String NS_XMLSCHEMA = "http://www.w3.org/2001/XMLSchema".intern(); public static final String NS_DTD = "http://www.w3.org/TR/REC-xml".intern(); + // Schema Versions: + public static final String W3C_XML_SCHEMA10_NS_URI = "http://www.w3.org/XML/XMLSchema/v1.0".intern(); + // Schema features public static final String SUN_SCHEMA_FEATURE_PREFIX = "http://java.sun.com/xml/schema/features/"; public static final String SUN_REPORT_IGNORED_ELEMENT_CONTENT_WHITESPACE = "report-ignored-element-content-whitespace"; @@ -487,6 +487,40 @@ public final class Constants { /** XInclude fixup language feature ("xinclude/fixup-language"). */ public static final String XINCLUDE_FIXUP_LANGUAGE_FEATURE = "xinclude/fixup-language"; + /** + * Feature to ignore xsi:type attributes on elements during validation, + * until a global element declaration is found. ("validation/schema/ignore-xsi-type-until-elemdecl") + * If this feature is on when validating a document, then beginning at the validation root + * element, xsi:type attributes are ignored until a global element declaration is + * found for an element. Once a global element declaration has been found, xsi:type + * attributes will start being processed for the sub-tree beginning at the element for + * which the declaration was found. + * + * Suppose an element A has two element children, B and C. + * + * If a global element declaration is found for A, xsi:type attributes on A, B and C, + * and all of B and C's descendents, will be processed. + * + * If no global element declaration is found for A or B, but one is found for C, + * then xsi:type attributes will be ignored on A and B (and any descendents of B, + * until a global element declaration is found), but xsi:type attributes will be + * processed for C and all of C's descendents. + * + * Once xsi:type attributes stop being ignored for a subtree, they do not start + * being ignored again, even if more elements are encountered for which no global + * element declaration can be found. + */ + public static final String IGNORE_XSI_TYPE_FEATURE = "validation/schema/ignore-xsi-type-until-elemdecl"; + + /** Perform checking of ID/IDREFs ("validation/id-idref-checking") */ + public static final String ID_IDREF_CHECKING_FEATURE = "validation/id-idref-checking"; + + /** Feature to ignore errors caused by identity constraints ("validation/identity-constraint-checking") */ + public static final String IDC_CHECKING_FEATURE = "validation/identity-constraint-checking"; + + /** Feature to ignore errors caused by unparsed entities ("validation/unparsed-entity-checking") */ + public static final String UNPARSED_ENTITY_CHECKING_FEATURE = "validation/unparsed-entity-checking"; + /** * Internal feature. When set to true the schema validator will only use * schema components from the grammar pool provided. @@ -598,6 +632,8 @@ public final class Constants { /** Validation manager property ("internal/validation-manager"). */ public static final String VALIDATION_MANAGER_PROPERTY = "internal/validation-manager"; + /** Schema type of the root element in a document ("validation/schema/root-type-definition"). */ + public static final String ROOT_TYPE_DEFINITION_PROPERTY = "validation/schema/root-type-definition"; /** XPointer Schema property ("xpointer-schema"). */ public static final String XPOINTER_SCHEMA_PROPERTY = "xpointer-schema"; @@ -739,6 +775,10 @@ public final class Constants { XINCLUDE_FEATURE, XINCLUDE_FIXUP_BASE_URIS_FEATURE, XINCLUDE_FIXUP_LANGUAGE_FEATURE, + IGNORE_XSI_TYPE_FEATURE, + ID_IDREF_CHECKING_FEATURE, + IDC_CHECKING_FEATURE, + UNPARSED_ENTITY_CHECKING_FEATURE, NAMESPACE_GROWTH_FEATURE, TOLERATE_DUPLICATES_FEATURE, }; @@ -762,6 +802,7 @@ public final class Constants { VALIDATION_MANAGER_PROPERTY, BUFFER_SIZE_PROPERTY, SECURITY_MANAGER_PROPERTY, + ROOT_TYPE_DEFINITION_PROPERTY, LOCALE_PROPERTY, SCHEMA_DV_FACTORY_PROPERTY, }; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java index 28fbc69270e..58700e2934b 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/XMLScanner.java @@ -973,6 +973,7 @@ public abstract class XMLScanner fStringBuffer2.append('\n'); } } else if (c != -1 && XMLChar.isHighSurrogate(c)) { + fStringBuffer3.clear(); if (scanSurrogates(fStringBuffer3)) { stringBuffer.append(fStringBuffer3); if (entityDepth == fEntityDepth && fNeedNonNormalizedValue) { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/ValidatedInfo.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/ValidatedInfo.java index e6b8f267a5d..cc84353bd64 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/ValidatedInfo.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/dv/ValidatedInfo.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001, 2002,2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -21,6 +18,7 @@ package com.sun.org.apache.xerces.internal.impl.dv; import com.sun.org.apache.xerces.internal.xs.ShortList; +import com.sun.org.apache.xerces.internal.xs.XSConstants; /** * Class to get the information back after content is validated. This info @@ -95,4 +93,60 @@ public class ValidatedInfo { else return actualValue.toString(); } + + /** + * Returns true if the two ValidatedInfo objects can be compared in the same + * value space. + */ + public static boolean isComparable(ValidatedInfo info1, ValidatedInfo info2) { + final short primitiveType1 = convertToPrimitiveKind(info1.actualValueType); + final short primitiveType2 = convertToPrimitiveKind(info2.actualValueType); + if (primitiveType1 != primitiveType2) { + return (primitiveType1 == XSConstants.ANYSIMPLETYPE_DT && primitiveType2 == XSConstants.STRING_DT || + primitiveType1 == XSConstants.STRING_DT && primitiveType2 == XSConstants.ANYSIMPLETYPE_DT); + } + else if (primitiveType1 == XSConstants.LIST_DT || primitiveType1 == XSConstants.LISTOFUNION_DT) { + final ShortList typeList1 = info1.itemValueTypes; + final ShortList typeList2 = info2.itemValueTypes; + final int typeList1Length = typeList1 != null ? typeList1.getLength() : 0; + final int typeList2Length = typeList2 != null ? typeList2.getLength() : 0; + if (typeList1Length != typeList2Length) { + return false; + } + for (int i = 0; i < typeList1Length; ++i) { + final short primitiveItem1 = convertToPrimitiveKind(typeList1.item(i)); + final short primitiveItem2 = convertToPrimitiveKind(typeList2.item(i)); + if (primitiveItem1 != primitiveItem2) { + if (primitiveItem1 == XSConstants.ANYSIMPLETYPE_DT && primitiveItem2 == XSConstants.STRING_DT || + primitiveItem1 == XSConstants.STRING_DT && primitiveItem2 == XSConstants.ANYSIMPLETYPE_DT) { + continue; + } + return false; + } + } + } + return true; + } + + /** + * Returns the primitive type of the given type. + * @param valueType A value type as defined in XSConstants. + * @return The primitive type from which valueType was derived. + */ + private static short convertToPrimitiveKind(short valueType) { + /** Primitive datatypes. */ + if (valueType <= XSConstants.NOTATION_DT) { + return valueType; + } + /** Types derived from string. */ + if (valueType <= XSConstants.ENTITY_DT) { + return XSConstants.STRING_DT; + } + /** Types derived from decimal. */ + if (valueType <= XSConstants.POSITIVEINTEGER_DT) { + return XSConstants.DECIMAL_DT; + } + /** Other types. */ + return valueType; + } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties index d986140a86e..5b73376eb50 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages.properties @@ -14,20 +14,18 @@ # Identity constraints - AbsentKeyValue = Identity Constraint error (cvc-identity-constraint.4.2.1): element \"{0}\" has a key with no value. + AbsentKeyValue = cvc-identity-constraint.4.2.1.a: Element \"{0}\" has no value for the key \"{1}\". DuplicateField = Duplicate match in scope for field \"{0}\". - DuplicateKey = Duplicate key value [{0}] declared for identity constraint of element \"{1}\". - DuplicateUnique = Duplicate unique value [{0}] declared for identity constraint of element \"{1}\". - FieldMultipleMatch = Identity constraint error: field \"{0}\" matches more than one value within the scope of its selector; fields must match unique values. + DuplicateKey = cvc-identity-constraint.4.2.2: Duplicate key value [{0}] declared for identity constraint \"{2}\" of element \"{1}\". + DuplicateUnique = cvc-identity-constraint.4.1: Duplicate unique value [{0}] declared for identity constraint \"{2}\" of element \"{1}\". + FieldMultipleMatch = cvc-identity-constraint.3: Field \"{0}\" of identity constraint \"{1}\" matches more than one value within the scope of its selector; fields must match unique values. FixedDiffersFromActual = The content of this element is not equivalent to the value of the \"fixed\" attribute in the element's declaration in the schema. - KeyMatchesNillable = Identity Constraint error (cvc-identity-constraint.4.2.3): element \"{0}\" has a key which matches an element which has nillable set to true. - KeyNotEnoughValues = Not enough values specified for identity constraint specified for element \"{0}\". - KeyNotFound = Key ''{0}'' with value ''{1}'' not found for identity constraint of element ''{2}''. - KeyRefNotEnoughValues = Not enough values specified for identity constraint specified for element \"{0}\". + KeyMatchesNillable = cvc-identity-constraint.4.2.3: Element \"{0}\" has the key \"{1}\" which matches an element which has nillable set to true. + KeyNotEnoughValues = cvc-identity-constraint.4.2.1.b: Not enough values specified for identity constraint specified for element \"{0}\". + KeyNotFound = cvc-identity-constraint.4.3: Key ''{0}'' with value ''{1}'' not found for identity constraint of element ''{2}''. KeyRefOutOfScope = Identity Constraint error: identity constraint \"{0}\" has a keyref which refers to a key or unique that is out of scope. KeyRefReferNotFound = Key reference declaration \"{0}\" refers to unknown key with name \"{1}\". - UniqueNotEnoughValues = Not enough values specified for identity constraint specified for element \"{0}\". - UnknownField = Internal identity constraint error; unknown field \"{0}\". + UnknownField = Internal identity constraint error; unknown field \"{0}\" for identity constraint \"{2}\" specified for element \"{1}\". # Ideally, we should only use the following error keys, not the ones under # "Identity constraints". And we should cover all of the following errors. @@ -79,6 +77,7 @@ cvc-minLength-valid = cvc-minLength-valid: Value ''{0}'' with length = ''{1}'' is not facet-valid with respect to minLength ''{2}'' for type ''{3}''. cvc-pattern-valid = cvc-pattern-valid: Value ''{0}'' is not facet-valid with respect to pattern ''{1}'' for type ''{2}''. cvc-totalDigits-valid = cvc-totalDigits-valid: Value ''{0}'' has {1} total digits, but the number of total digits has been limited to {2}. + cvc-type.1 = cvc-type.1: The type definition ''{0}'' was not found. cvc-type.2 = cvc-type.2: The type definition cannot be abstract for element {0}. cvc-type.3.1.1 = cvc-type.3.1.1: Element ''{0}'' is a simple type, so it cannot have attributes, excepting those whose namespace name is identical to ''http://www.w3.org/2001/XMLSchema-instance'' and whose [local name] is one of ''type'', ''nil'', ''schemaLocation'' or ''noNamespaceSchemaLocation''. However, the attribute, ''{1}'' was found. cvc-type.3.1.2 = cvc-type.3.1.2: Element ''{0}'' is a simple type, so it must have no element information item [children]. diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/validation/ConfigurableValidationState.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/validation/ConfigurableValidationState.java new file mode 100644 index 00000000000..ac8406dd325 --- /dev/null +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/validation/ConfigurableValidationState.java @@ -0,0 +1,123 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sun.org.apache.xerces.internal.impl.validation; + +/** + *

An extension of ValidationState which can be configured to turn + * off checking for ID/IDREF errors and unparsed entity errors.

+ * + * @xerces.internal + * + * @author Peter McCracken, IBM + */ +public final class ConfigurableValidationState extends ValidationState { + + /** + * Whether to check for ID/IDREF errors + */ + private boolean fIdIdrefChecking; + + /** + * Whether to check for unparsed entity errors + */ + private boolean fUnparsedEntityChecking; + + /** + * Creates a new ConfigurableValidationState. + * By default, error checking for both ID/IDREFs + * and unparsed entities are turned on. + */ + public ConfigurableValidationState() { + super(); + fIdIdrefChecking = true; + fUnparsedEntityChecking = true; + } + + /** + * Turns checking for ID/IDREF errors on and off. + * @param setting: true to turn on error checking + * false to turn off error checking + */ + public void setIdIdrefChecking(boolean setting) { + fIdIdrefChecking = setting; + } + + /** + * Turns checking for unparsed entity errors on and off. + * @param setting: true to turn on error checking + * false to turn off error checking + */ + public void setUnparsedEntityChecking(boolean setting) { + fUnparsedEntityChecking = setting; + } + + /** + * Checks if all IDREFs have a corresponding ID. + * @return null, if ID/IDREF checking is turned off + * otherwise, returns the value of the super implementation + */ + public String checkIDRefID() { + return (fIdIdrefChecking) ? super.checkIDRefID() : null; + } + + /** + * Checks if an ID has already been declared. + * @return false, if ID/IDREF checking is turned off + * otherwise, returns the value of the super implementation + */ + public boolean isIdDeclared(String name) { + return (fIdIdrefChecking) ? super.isIdDeclared(name) : false; + } + + /** + * Checks if an entity is declared. + * @return true, if unparsed entity checking is turned off + * otherwise, returns the value of the super implementation + */ + public boolean isEntityDeclared(String name) { + return (fUnparsedEntityChecking) ? super.isEntityDeclared(name) : true; + } + + /** + * Checks if an entity is unparsed. + * @return true, if unparsed entity checking is turned off + * otherwise, returns the value of the super implementation + */ + public boolean isEntityUnparsed(String name) { + return (fUnparsedEntityChecking) ? super.isEntityUnparsed(name) : true; + } + + /** + * Adds the ID, if ID/IDREF checking is enabled. + * @param the ID to add + */ + public void addId(String name) { + if (fIdIdrefChecking) { + super.addId(name); + } + } + + /** + * Adds the IDREF, if ID/IDREF checking is enabled. + * @param the IDREF to add + */ + public void addIdRef(String name) { + if (fIdIdrefChecking) { + super.addIdRef(name); + } + } +} diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java index fd03b7a8f75..dbe788ac599 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/xs/XMLSchemaValidator.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 1999-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -38,6 +35,7 @@ import com.sun.org.apache.xerces.internal.impl.dv.DatatypeException; import com.sun.org.apache.xerces.internal.impl.dv.InvalidDatatypeValueException; import com.sun.org.apache.xerces.internal.impl.dv.ValidatedInfo; import com.sun.org.apache.xerces.internal.impl.dv.XSSimpleType; +import com.sun.org.apache.xerces.internal.impl.validation.ConfigurableValidationState; import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager; import com.sun.org.apache.xerces.internal.impl.validation.ValidationState; import com.sun.org.apache.xerces.internal.impl.xs.identity.Field; @@ -185,6 +183,22 @@ public class XMLSchemaValidator protected static final String TOLERATE_DUPLICATES = Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE; + /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ + protected static final String IGNORE_XSI_TYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; + + /** Feature identifier: whether to ignore ID/IDREF errors */ + protected static final String ID_IDREF_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore unparsed entity errors */ + protected static final String UNPARSED_ENTITY_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore identity constraint errors */ + protected static final String IDENTITY_CONSTRAINT_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; + protected static final String REPORT_WHITESPACE = Constants.SUN_SCHEMA_FEATURE_PREFIX + Constants.SUN_REPORT_IGNORED_ELEMENT_CONTENT_WHITESPACE; @@ -228,6 +242,10 @@ public class XMLSchemaValidator protected static final String JAXP_SCHEMA_LANGUAGE = Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE; + /** Property identifier: root type definition. */ + protected static final String ROOT_TYPE_DEF = + Constants.XERCES_PROPERTY_PREFIX + Constants.ROOT_TYPE_DEFINITION_PROPERTY; + /** Property identifier: Schema DV Factory */ protected static final String SCHEMA_DV_FACTORY = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; @@ -254,6 +272,10 @@ public class XMLSchemaValidator VALIDATE_ANNOTATIONS, HONOUR_ALL_SCHEMALOCATIONS, USE_GRAMMAR_POOL_ONLY, + IGNORE_XSI_TYPE, + ID_IDREF_CHECKING, + IDENTITY_CONSTRAINT_CHECKING, + UNPARSED_ENTITY_CHECKING, NAMESPACE_GROWTH, TOLERATE_DUPLICATES, USE_SERVICE_MECHANISM @@ -267,6 +289,10 @@ public class XMLSchemaValidator // those set by the application. This goes against the // whole purpose of XMLComponent#getFeatureDefault but // it can't be helped in this case. -Ac + // NOTE: Instead of adding default values here, add them (and + // the corresponding recognized features) to the objects + // that have an XMLSchemaValidator instance as a member, + // such as the parser configurations. -PM null, //Boolean.FALSE, null, //Boolean.FALSE, null, //Boolean.FALSE, @@ -279,6 +305,10 @@ public class XMLSchemaValidator null, null, null, + null, + null, + null, + null, Boolean.TRUE }; @@ -293,13 +323,14 @@ public class XMLSchemaValidator SCHEMA_NONS_LOCATION, JAXP_SCHEMA_SOURCE, JAXP_SCHEMA_LANGUAGE, + ROOT_TYPE_DEF, SCHEMA_DV_FACTORY, XML_SECURITY_PROPERTY_MANAGER }; /** Property defaults. */ private static final Object[] PROPERTY_DEFAULTS = - { null, null, null, null, null, null, null, null, null, null, null, null, null}; + { null, null, null, null, null, null, null, null, null, null, null}; // this is the number of valuestores of each kind // we expect an element to have. It's almost @@ -482,7 +513,7 @@ public class XMLSchemaValidator // updated during reset protected ValidationManager fValidationManager = null; - protected ValidationState fValidationState = new ValidationState(); + protected ConfigurableValidationState fValidationState = new ConfigurableValidationState(); protected XMLGrammarPool fGrammarPool; // schema location property values @@ -562,6 +593,9 @@ public class XMLSchemaValidator * this exception. */ public void setProperty(String propertyId, Object value) throws XMLConfigurationException { + if (propertyId.equals(ROOT_TYPE_DEF)) { + fRootTypeQName = (javax.xml.namespace.QName)value; + } } // setProperty(String,Object) /** @@ -1234,6 +1268,12 @@ public class XMLSchemaValidator /** temporary qname */ private final QName fTempQName = new QName(); + private javax.xml.namespace.QName fRootTypeQName = null; + + private int fIgnoreXSITypeDepth; + + private boolean fIDCChecking; + /** temporary validated info */ private ValidatedInfo fValidatedInfo = new ValidatedInfo(); @@ -1384,6 +1424,38 @@ public class XMLSchemaValidator fValidationManager.addValidationState(fValidationState); fValidationState.setSymbolTable(fSymbolTable); + boolean ignoreXSIType; + try { + ignoreXSIType = componentManager.getFeature(IGNORE_XSI_TYPE); + } + catch (XMLConfigurationException e) { + ignoreXSIType = false; + } + // An initial value of -1 means that the root element considers itself + // below the depth where xsi:type stopped being ignored (which means that + // xsi:type attributes will not be ignored for the entire document) + fIgnoreXSITypeDepth = ignoreXSIType ? 0 : -1; + + try { + fIDCChecking = componentManager.getFeature(IDENTITY_CONSTRAINT_CHECKING); + } + catch (XMLConfigurationException e) { + fIDCChecking = true; + } + + try { + fValidationState.setIdIdrefChecking(componentManager.getFeature(ID_IDREF_CHECKING)); + } + catch (XMLConfigurationException e) { + fValidationState.setIdIdrefChecking(true); + } + + try { + fValidationState.setUnparsedEntityChecking(componentManager.getFeature(UNPARSED_ENTITY_CHECKING)); + } + catch (XMLConfigurationException e) { + fValidationState.setUnparsedEntityChecking(true); + } // get schema location properties try { @@ -1550,7 +1622,9 @@ public class XMLSchemaValidator // handle start document void handleStartDocument(XMLLocator locator, String encoding) { - fValueStoreCache.startDocument(); + if (fIDCChecking) { + fValueStoreCache.startDocument(); + } if (fAugPSVI) { fCurrentPSVI.fGrammars = null; fCurrentPSVI.fSchemaInformation = null; @@ -1558,7 +1632,9 @@ public class XMLSchemaValidator } // handleStartDocument(XMLLocator,String) void handleEndDocument() { - fValueStoreCache.endDocument(); + if (fIDCChecking) { + fValueStoreCache.endDocument(); + } } // handleEndDocument() // handle character contents @@ -1850,22 +1926,54 @@ public class XMLSchemaValidator return augs; } - // try again to get the element decl: - // case 1: find declaration for root element - // case 2: find declaration for element from another namespace - if (fCurrentElemDecl == null) { - if (sGrammar != null) { - fCurrentElemDecl = sGrammar.getGlobalElementDecl(element.localpart); + // 1.2.1.1 A type definition was stipulated by the processor + if (fElementDepth == 0 && fRootTypeQName != null) { + String rootTypeNamespace = fRootTypeQName.getNamespaceURI(); + if (rootTypeNamespace != null && rootTypeNamespace.equals(XMLConstants.NULL_NS_URI)) { + rootTypeNamespace = null; + } + SchemaGrammar grammarForRootType = + findSchemaGrammar( + XSDDescription.CONTEXT_ELEMENT, rootTypeNamespace, null, null, null); + if (grammarForRootType != null) { + fCurrentType = grammarForRootType.getGlobalTypeDecl(fRootTypeQName.getLocalPart()); + } + if (fCurrentType == null) { + String typeName = (fRootTypeQName.getPrefix().equals(XMLConstants.DEFAULT_NS_PREFIX)) ? + fRootTypeQName.getLocalPart() : + fRootTypeQName.getPrefix()+":"+fRootTypeQName.getLocalPart(); + reportSchemaError("cvc-type.1", new Object[] {typeName}); } } - if (fCurrentElemDecl != null) { - // then get the type - fCurrentType = fCurrentElemDecl.fType; + // if there was no processor stipulated type + if (fCurrentType == null) { + // try again to get the element decl: + // case 1: find declaration for root element + // case 2: find declaration for element from another namespace + if (fCurrentElemDecl == null) { + if (sGrammar != null) { + fCurrentElemDecl = sGrammar.getGlobalElementDecl(element.localpart); + } + } + + if (fCurrentElemDecl != null) { + // then get the type + fCurrentType = fCurrentElemDecl.fType; + } } - // get type from xsi:type - String xsiType = attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_TYPE); + + // check if we should be ignoring xsi:type on this element + if (fElementDepth == fIgnoreXSITypeDepth && fCurrentElemDecl == null) { + fIgnoreXSITypeDepth++; + } + + // process xsi:type attribute information + String xsiType = null; + if (fElementDepth >= fIgnoreXSITypeDepth) { + xsiType = attributes.getValue(SchemaSymbols.URI_XSI, SchemaSymbols.XSI_TYPE); + } // if no decl/type found for the current element if (fCurrentType == null && xsiType == null) { @@ -2044,13 +2152,17 @@ public class XMLSchemaValidator XSComplexTypeDecl ctype = (XSComplexTypeDecl) fCurrentType; attrGrp = ctype.getAttrGrp(); } - // activate identity constraints - fValueStoreCache.startElement(); - fMatcherStack.pushContext(); - if (fCurrentElemDecl != null && fCurrentElemDecl.fIDCPos > 0) { - fIdConstraint = true; - // initialize when identity constrains are defined for the elem - fValueStoreCache.initValueStoresFor(fCurrentElemDecl, this); + + if (fIDCChecking) { + // activate identity constraints + fValueStoreCache.startElement(); + fMatcherStack.pushContext(); + //if (fCurrentElemDecl != null && fCurrentElemDecl.fIDCPos > 0 && !fIgnoreIDC) { + if (fCurrentElemDecl != null && fCurrentElemDecl.fIDCPos > 0) { + fIdConstraint = true; + // initialize when identity constrains are defined for the elem + fValueStoreCache.initValueStoresFor(fCurrentElemDecl, this); + } } processAttributes(element, attributes, attrGrp); @@ -2138,66 +2250,75 @@ public class XMLSchemaValidator // now validate the content of the element processElementContent(element); - // Element Locally Valid (Element) - // 6 The element information item must be valid with respect to each of the {identity-constraint definitions} as per Identity-constraint Satisfied (3.11.4). + if (fIDCChecking) { + // Element Locally Valid (Element) + // 6 The element information item must be valid with respect to each of the {identity-constraint definitions} as per Identity-constraint Satisfied (3.11.4). - // call matchers and de-activate context - int oldCount = fMatcherStack.getMatcherCount(); - for (int i = oldCount - 1; i >= 0; i--) { - XPathMatcher matcher = fMatcherStack.getMatcherAt(i); - if (fCurrentElemDecl == null) - matcher.endElement(element, null, false, fValidatedInfo.actualValue, fValidatedInfo.actualValueType, fValidatedInfo.itemValueTypes); + // call matchers and de-activate context + int oldCount = fMatcherStack.getMatcherCount(); + for (int i = oldCount - 1; i >= 0; i--) { + XPathMatcher matcher = fMatcherStack.getMatcherAt(i); + if (fCurrentElemDecl == null) + matcher.endElement(element, null, false, fValidatedInfo.actualValue, fValidatedInfo.actualValueType, fValidatedInfo.itemValueTypes); - else - matcher.endElement( - element, - fCurrentType, - fCurrentElemDecl.getNillable(), - fDefaultValue == null - ? fValidatedInfo.actualValue - : fCurrentElemDecl.fDefault.actualValue, - fDefaultValue == null - ? fValidatedInfo.actualValueType - : fCurrentElemDecl.fDefault.actualValueType, - fDefaultValue == null - ? fValidatedInfo.itemValueTypes - : fCurrentElemDecl.fDefault.itemValueTypes); - } + else + matcher.endElement( + element, + fCurrentType, + fCurrentElemDecl.getNillable(), + fDefaultValue == null + ? fValidatedInfo.actualValue + : fCurrentElemDecl.fDefault.actualValue, + fDefaultValue == null + ? fValidatedInfo.actualValueType + : fCurrentElemDecl.fDefault.actualValueType, + fDefaultValue == null + ? fValidatedInfo.itemValueTypes + : fCurrentElemDecl.fDefault.itemValueTypes); + } - if (fMatcherStack.size() > 0) { - fMatcherStack.popContext(); - } + if (fMatcherStack.size() > 0) { + fMatcherStack.popContext(); + } - int newCount = fMatcherStack.getMatcherCount(); - // handle everything *but* keyref's. - for (int i = oldCount - 1; i >= newCount; i--) { - XPathMatcher matcher = fMatcherStack.getMatcherAt(i); - if (matcher instanceof Selector.Matcher) { - Selector.Matcher selMatcher = (Selector.Matcher) matcher; - IdentityConstraint id; - if ((id = selMatcher.getIdentityConstraint()) != null - && id.getCategory() != IdentityConstraint.IC_KEYREF) { - fValueStoreCache.transplant(id, selMatcher.getInitialDepth()); + int newCount = fMatcherStack.getMatcherCount(); + // handle everything *but* keyref's. + for (int i = oldCount - 1; i >= newCount; i--) { + XPathMatcher matcher = fMatcherStack.getMatcherAt(i); + if (matcher instanceof Selector.Matcher) { + Selector.Matcher selMatcher = (Selector.Matcher) matcher; + IdentityConstraint id; + if ((id = selMatcher.getIdentityConstraint()) != null + && id.getCategory() != IdentityConstraint.IC_KEYREF) { + fValueStoreCache.transplant(id, selMatcher.getInitialDepth()); + } } } - } - // now handle keyref's/... - for (int i = oldCount - 1; i >= newCount; i--) { - XPathMatcher matcher = fMatcherStack.getMatcherAt(i); - if (matcher instanceof Selector.Matcher) { - Selector.Matcher selMatcher = (Selector.Matcher) matcher; - IdentityConstraint id; - if ((id = selMatcher.getIdentityConstraint()) != null - && id.getCategory() == IdentityConstraint.IC_KEYREF) { - ValueStoreBase values = - fValueStoreCache.getValueStoreFor(id, selMatcher.getInitialDepth()); - if (values != null) // nothing to do if nothing matched! - values.endDocumentFragment(); + // now handle keyref's/... + for (int i = oldCount - 1; i >= newCount; i--) { + XPathMatcher matcher = fMatcherStack.getMatcherAt(i); + if (matcher instanceof Selector.Matcher) { + Selector.Matcher selMatcher = (Selector.Matcher) matcher; + IdentityConstraint id; + if ((id = selMatcher.getIdentityConstraint()) != null + && id.getCategory() == IdentityConstraint.IC_KEYREF) { + ValueStoreBase values = + fValueStoreCache.getValueStoreFor(id, selMatcher.getInitialDepth()); + if (values != null) // nothing to do if nothing matched! + values.endDocumentFragment(); + } } } + fValueStoreCache.endElement(); + } + + // Check if we should modify the xsi:type ignore depth + // This check is independent of whether this is the validation root, + // and should be done before the element depth is decremented. + if (fElementDepth < fIgnoreXSITypeDepth) { + fIgnoreXSITypeDepth--; } - fValueStoreCache.endElement(); SchemaGrammar[] grammars = null; // have we reached the end tag of the validation root? @@ -2290,7 +2411,14 @@ public class XMLSchemaValidator // otherwise partial, and anything above this level will be partial else { fCurrentPSVI.fValidationAttempted = ElementPSVI.VALIDATION_PARTIAL; - fNFullValidationDepth = fNNoneValidationDepth = fElementDepth - 1; + } + + // this guarantees that depth settings do not cross-over between sibling nodes + if (fNFullValidationDepth == fElementDepth) { + fNFullValidationDepth = fElementDepth - 1; + } + if (fNNoneValidationDepth == fElementDepth) { + fNNoneValidationDepth = fElementDepth - 1; } if (fDefaultValue != null) @@ -2554,14 +2682,22 @@ public class XMLSchemaValidator // if there is no current type, set this one as current. // and we don't need to do extra checking if (fCurrentType != null) { + short block = XSConstants.DERIVATION_NONE; // 4.3 The local type definition must be validly derived from the {type definition} given the union of the {disallowed substitutions} and the {type definition}'s {prohibited substitutions}, as defined in Type Derivation OK (Complex) (3.4.6) (if it is a complex type definition), or given {disallowed substitutions} as defined in Type Derivation OK (Simple) (3.14.6) (if it is a simple type definition). - short block = fCurrentElemDecl.fBlock; - if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) + // Note: It's possible to have fCurrentType be non-null and fCurrentElemDecl + // be null, if the current type is set using the property "root-type-definition". + // In that case, we don't disallow any substitutions. -PM + if (fCurrentElemDecl != null) { + block = fCurrentElemDecl.fBlock; + } + if (fCurrentType.getTypeCategory() == XSTypeDefinition.COMPLEX_TYPE) { block |= ((XSComplexTypeDecl) fCurrentType).fBlock; - if (!XSConstraints.checkTypeDerivationOk(type, fCurrentType, block)) + } + if (!XSConstraints.checkTypeDerivationOk(type, fCurrentType, block)) { reportSchemaError( - "cvc-elt.4.3", - new Object[] { element.rawname, xsiType, fCurrentType.getName()}); + "cvc-elt.4.3", + new Object[] { element.rawname, xsiType, fCurrentType.getName()}); + } } return type; @@ -2835,9 +2971,10 @@ public class XMLSchemaValidator } // get the value constraint from use or decl - // 4 The item's actual value must match the value of the {value constraint}, if it is present and fixed. // now check the value against the simpleType + // 4 The item's actual value must match the value of the {value constraint}, if it is present and fixed. + // now check the value against the simpleType if (actualValue != null && currDecl.getConstraintType() == XSConstants.VC_FIXED) { - if (!isComparable(fValidatedInfo, currDecl.fDefault) || !actualValue.equals(currDecl.fDefault.actualValue)) { + if (!ValidatedInfo.isComparable(fValidatedInfo, currDecl.fDefault) || !actualValue.equals(currDecl.fDefault.actualValue)) { reportSchemaError( "cvc-attribute.4", new Object[] { @@ -2852,7 +2989,7 @@ public class XMLSchemaValidator if (actualValue != null && currUse != null && currUse.fConstraintType == XSConstants.VC_FIXED) { - if (!isComparable(fValidatedInfo, currUse.fDefault) || !actualValue.equals(currUse.fDefault.actualValue)) { + if (!ValidatedInfo.isComparable(fValidatedInfo, currUse.fDefault) || !actualValue.equals(currUse.fDefault.actualValue)) { reportSchemaError( "cvc-complex-type.3.1", new Object[] { @@ -3083,7 +3220,7 @@ public class XMLSchemaValidator } // 5.2.2.2.2 If the {content type} of the actual type definition is a simple type definition, then the actual value of the item must match the canonical lexical representation of the {value constraint} value. else if (ctype.fContentType == XSComplexTypeDecl.CONTENTTYPE_SIMPLE) { - if (actualValue != null && (!isComparable(fValidatedInfo, fCurrentElemDecl.fDefault) + if (actualValue != null && (!ValidatedInfo.isComparable(fValidatedInfo, fCurrentElemDecl.fDefault) || !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))) { reportSchemaError( "cvc-elt.5.2.2.2.2", @@ -3094,7 +3231,7 @@ public class XMLSchemaValidator } } } else if (fCurrentType.getTypeCategory() == XSTypeDefinition.SIMPLE_TYPE) { - if (actualValue != null && (!isComparable(fValidatedInfo, fCurrentElemDecl.fDefault) + if (actualValue != null && (!ValidatedInfo.isComparable(fValidatedInfo, fCurrentElemDecl.fDefault) || !actualValue.equals(fCurrentElemDecl.fDefault.actualValue))) { // REVISIT: the spec didn't mention this case: fixed // value with simple type @@ -3240,53 +3377,6 @@ public class XMLSchemaValidator XMLErrorReporter.SEVERITY_ERROR); } - /** Returns true if the two ValidatedInfo objects can be compared in the same value space. **/ - private boolean isComparable(ValidatedInfo info1, ValidatedInfo info2) { - final short primitiveType1 = convertToPrimitiveKind(info1.actualValueType); - final short primitiveType2 = convertToPrimitiveKind(info2.actualValueType); - if (primitiveType1 != primitiveType2) { - return (primitiveType1 == XSConstants.ANYSIMPLETYPE_DT && primitiveType2 == XSConstants.STRING_DT || - primitiveType1 == XSConstants.STRING_DT && primitiveType2 == XSConstants.ANYSIMPLETYPE_DT); - } - else if (primitiveType1 == XSConstants.LIST_DT || primitiveType1 == XSConstants.LISTOFUNION_DT) { - final ShortList typeList1 = info1.itemValueTypes; - final ShortList typeList2 = info2.itemValueTypes; - final int typeList1Length = typeList1 != null ? typeList1.getLength() : 0; - final int typeList2Length = typeList2 != null ? typeList2.getLength() : 0; - if (typeList1Length != typeList2Length) { - return false; - } - for (int i = 0; i < typeList1Length; ++i) { - final short primitiveItem1 = convertToPrimitiveKind(typeList1.item(i)); - final short primitiveItem2 = convertToPrimitiveKind(typeList2.item(i)); - if (primitiveItem1 != primitiveItem2) { - if (primitiveItem1 == XSConstants.ANYSIMPLETYPE_DT && primitiveItem2 == XSConstants.STRING_DT || - primitiveItem1 == XSConstants.STRING_DT && primitiveItem2 == XSConstants.ANYSIMPLETYPE_DT) { - continue; - } - return false; - } - } - } - return true; - } - - private short convertToPrimitiveKind(short valueType) { - /** Primitive datatypes. */ - if (valueType <= XSConstants.NOTATION_DT) { - return valueType; - } - /** Types derived from string. */ - if (valueType <= XSConstants.ENTITY_DT) { - return XSConstants.STRING_DT; - } - /** Types derived from decimal. */ - if (valueType <= XSConstants.POSITIVEINTEGER_DT) { - return XSConstants.DECIMAL_DT; - } - /** Other types. */ - return valueType; - } private String expectedStr(Vector expected) { StringBuffer ret = new StringBuffer("{"); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchema.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchema.java index 070086aa98b..5b05a6d1c28 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchema.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchema.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -32,11 +29,19 @@ final class XMLSchema extends AbstractXMLSchema { /** The grammar pool is immutable */ private final XMLGrammarPool fGrammarPool; + /** Whether to consider this schema to be fully composed */ + private final boolean fFullyComposed; + /** Constructor */ public XMLSchema(XMLGrammarPool grammarPool) { - fGrammarPool = grammarPool; + this(grammarPool, true); } + public XMLSchema(XMLGrammarPool grammarPool, boolean fullyComposed) { + fGrammarPool = grammarPool; + fFullyComposed = fullyComposed; + } + /* * XSGrammarPoolContainer methods */ @@ -60,7 +65,7 @@ final class XMLSchema extends AbstractXMLSchema { * can be considered to be a fully composed schema */ public boolean isFullyComposed() { - return true; + return fFullyComposed; } } // XMLSchema diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java index a453dbf4227..3542750efaf 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaFactory.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -68,12 +65,21 @@ import org.xml.sax.SAXParseException; */ public final class XMLSchemaFactory extends SchemaFactory { - // property identifiers + // feature identifiers + + /** JAXP Source feature prefix. */ + private static final String JAXP_SOURCE_FEATURE_PREFIX = "http://javax.xml.transform"; /** Feature identifier: schema full checking. */ private static final String SCHEMA_FULL_CHECKING = Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING; + /** Feature identifier: use grammar pool only. */ + private static final String USE_GRAMMAR_POOL_ONLY = + Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE; + + // property identifiers + /** Property identifier: grammar pool. */ private static final String XMLGRAMMAR_POOL = Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY; @@ -104,7 +110,7 @@ public final class XMLSchemaFactory extends SchemaFactory { private final DOMEntityResolverWrapper fDOMEntityResolverWrapper; /** The ErrorHandlerWrapper */ - private ErrorHandlerWrapper fErrorHandlerWrapper; + private final ErrorHandlerWrapper fErrorHandlerWrapper; /** The SecurityManager. */ private XMLSecurityManager fSecurityManager; @@ -113,7 +119,10 @@ public final class XMLSchemaFactory extends SchemaFactory { private XMLSecurityPropertyManager fSecurityPropertyMgr; /** The container for the real grammar pool. */ - private XMLGrammarPoolWrapper fXMLGrammarPoolWrapper; + private final XMLGrammarPoolWrapper fXMLGrammarPoolWrapper; + + /** Whether or not to allow new schemas to be added to the grammar pool */ + private boolean fUseGrammarPoolOnly; /** * Indicates whether implementation parts should use @@ -138,6 +147,7 @@ public final class XMLSchemaFactory extends SchemaFactory { fXMLSchemaLoader.setProperty(XMLGRAMMAR_POOL, fXMLGrammarPoolWrapper); fXMLSchemaLoader.setEntityResolver(fDOMEntityResolverWrapper); fXMLSchemaLoader.setErrorHandler(fErrorHandlerWrapper); + fUseGrammarPoolOnly = true; // Enable secure processing feature by default fSecurityManager = new XMLSecurityManager(true); @@ -170,7 +180,8 @@ public final class XMLSchemaFactory extends SchemaFactory { "SchemaLanguageLengthZero", null)); } // only W3C XML Schema 1.0 is supported - return schemaLanguage.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI); + return schemaLanguage.equals(XMLConstants.W3C_XML_SCHEMA_NS_URI) || + schemaLanguage.equals(Constants.W3C_XML_SCHEMA10_NS_URI); } public LSResourceResolver getResourceResolver() { @@ -202,7 +213,7 @@ public final class XMLSchemaFactory extends SchemaFactory { XMLInputSource[] xmlInputSources = new XMLInputSource[schemas.length]; InputStream inputStream; Reader reader; - for( int i=0; i 1) { - schema = new XMLSchema(new ReadOnlyGrammarPool(pool)); - } - else if (grammarCount == 1) { - Grammar[] grammars = pool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_SCHEMA); - schema = new SimpleXMLSchema(grammars[0]); + if (fUseGrammarPoolOnly) { + if (grammarCount > 1) { + schema = new XMLSchema(new ReadOnlyGrammarPool(pool)); + } + else if (grammarCount == 1) { + Grammar[] grammars = pool.retrieveInitialGrammarSet(XMLGrammarDescription.XML_SCHEMA); + schema = new SimpleXMLSchema(grammars[0]); + } + else { + schema = new EmptyXMLSchema(); + } } else { - schema = new EmptyXMLSchema(); + schema = new XMLSchema(new ReadOnlyGrammarPool(pool), false); } propagateFeatures(schema); propagateProperties(schema); @@ -286,6 +305,14 @@ public final class XMLSchemaFactory extends SchemaFactory { } public Schema newSchema() throws SAXException { + /* + * It would make sense to return an EmptyXMLSchema object here, if + * fUseGrammarPoolOnly is set to true. However, because the default + * value of this feature is true, doing so would change the default + * behaviour of this method. Thus, we return a WeakReferenceXMLSchema + * regardless of the value of fUseGrammarPoolOnly. -PM + */ + // Use a Schema that uses the system id as the equality source. AbstractXMLSchema schema = new WeakReferenceXMLSchema(); propagateFeatures(schema); @@ -293,15 +320,38 @@ public final class XMLSchemaFactory extends SchemaFactory { return schema; } + public Schema newSchema(XMLGrammarPool pool) throws SAXException { + // If the "use-grammar-pool-only" feature is set to true + // prevent the application's grammar pool from being mutated + // by wrapping it in a ReadOnlyGrammarPool. + final AbstractXMLSchema schema = (fUseGrammarPoolOnly) ? + new XMLSchema(new ReadOnlyGrammarPool(pool)) : + new XMLSchema(pool, false); + propagateFeatures(schema); + return schema; + } + public boolean getFeature(String name) throws SAXNotRecognizedException, SAXNotSupportedException { if (name == null) { throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), "FeatureNameNull", null)); } + if (name.startsWith(JAXP_SOURCE_FEATURE_PREFIX)) { + // Indicates to the caller that this SchemaFactory supports a specific JAXP Source. + if (name.equals(StreamSource.FEATURE) || + name.equals(SAXSource.FEATURE) || + name.equals(DOMSource.FEATURE) || + name.equals(StAXSource.FEATURE)) { + return true; + } + } if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { return (fSecurityManager != null && fSecurityManager.isSecureProcessing()); } + else if (name.equals(USE_GRAMMAR_POOL_ONLY)) { + return fUseGrammarPoolOnly; + } try { return fXMLSchemaLoader.getFeature(name); } @@ -358,6 +408,16 @@ public final class XMLSchemaFactory extends SchemaFactory { throw new NullPointerException(JAXPValidationMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), "FeatureNameNull", null)); } + if (name.startsWith(JAXP_SOURCE_FEATURE_PREFIX)) { + if (name.equals(StreamSource.FEATURE) || + name.equals(SAXSource.FEATURE) || + name.equals(DOMSource.FEATURE) || + name.equals(StAXSource.FEATURE)) { + throw new SAXNotSupportedException( + SAXMessageFormatter.formatMessage(fXMLSchemaLoader.getLocale(), + "feature-read-only", new Object [] {name})); + } + } if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) { if (System.getSecurityManager() != null && (!value)) { throw new SAXNotSupportedException( @@ -377,7 +437,12 @@ public final class XMLSchemaFactory extends SchemaFactory { fXMLSchemaLoader.setProperty(SECURITY_MANAGER, fSecurityManager); return; - } else if (name.equals(Constants.ORACLE_FEATURE_SERVICE_MECHANISM)) { + } + else if (name.equals(USE_GRAMMAR_POOL_ONLY)) { + fUseGrammarPoolOnly = value; + return; + } + else if (name.equals(Constants.ORACLE_FEATURE_SERVICE_MECHANISM)) { //in secure mode, let _useServicesMechanism be determined by the constructor if (System.getSecurityManager() != null) return; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java index 58a74191cf0..807dc917908 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/jaxp/validation/XMLSchemaValidatorComponentManager.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -69,13 +66,41 @@ final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettin private static final String VALIDATION = Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE; + /** Feature identifier: use grammar pool only. */ + private static final String USE_GRAMMAR_POOL_ONLY = + Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE; + + /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ + protected static final String IGNORE_XSI_TYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; + + /** Feature identifier: whether to ignore ID/IDREF errors */ + protected static final String ID_IDREF_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore unparsed entity errors */ + protected static final String UNPARSED_ENTITY_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore identity constraint errors */ + protected static final String IDENTITY_CONSTRAINT_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; + + /** Feature identifier: disallow DOCTYPE declaration */ + private static final String DISALLOW_DOCTYPE_DECL_FEATURE = + Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE; + + /** Feature identifier: expose schema normalized value */ + private static final String NORMALIZE_DATA = + Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE; + /** Feature identifier: send element default value via characters() */ private static final String SCHEMA_ELEMENT_DEFAULT = Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT; - /** Feature identifier: use grammar pool only. */ - private static final String USE_GRAMMAR_POOL_ONLY = - Constants.XERCES_FEATURE_PREFIX + Constants.USE_GRAMMAR_POOL_ONLY_FEATURE; + /** Feature identifier: augment PSVI */ + private static final String SCHEMA_AUGMENT_PSVI = + Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI; // property identifiers @@ -230,10 +255,32 @@ final class XMLSchemaValidatorComponentManager extends ParserConfigurationSettin fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter()); // add all recognized features and properties and apply their defaults + final String [] recognizedFeatures = { + DISALLOW_DOCTYPE_DECL_FEATURE, + NORMALIZE_DATA, + SCHEMA_ELEMENT_DEFAULT, + SCHEMA_AUGMENT_PSVI + }; + addRecognizedFeatures(recognizedFeatures); + fFeatures.put(DISALLOW_DOCTYPE_DECL_FEATURE, Boolean.FALSE); + fFeatures.put(NORMALIZE_DATA, Boolean.FALSE); + fFeatures.put(SCHEMA_ELEMENT_DEFAULT, Boolean.FALSE); + fFeatures.put(SCHEMA_AUGMENT_PSVI, Boolean.TRUE); + addRecognizedParamsAndSetDefaults(fEntityManager, grammarContainer); addRecognizedParamsAndSetDefaults(fErrorReporter, grammarContainer); addRecognizedParamsAndSetDefaults(fSchemaValidator, grammarContainer); + /* TODO: are other XMLSchemaValidator default values never set? + * Initial investigation indicates that they aren't set, but + * that they all have default values of false, so it works out + * anyway -PM + */ + fFeatures.put(IGNORE_XSI_TYPE, Boolean.FALSE); + fFeatures.put(ID_IDREF_CHECKING, Boolean.TRUE); + fFeatures.put(IDENTITY_CONSTRAINT_CHECKING, Boolean.TRUE); + fFeatures.put(UNPARSED_ENTITY_CHECKING, Boolean.TRUE); + boolean secureProcessing = grammarContainer.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING); if (System.getSecurityManager() != null) { _isSecureMode = true; diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/StandardParserConfiguration.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/StandardParserConfiguration.java index 5ac09f8f866..464f93e8c92 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/StandardParserConfiguration.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/StandardParserConfiguration.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -109,6 +106,22 @@ public class StandardParserConfiguration protected static final String HONOUR_ALL_SCHEMALOCATIONS = Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE; + /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ + protected static final String IGNORE_XSI_TYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; + + /** Feature identifier: whether to ignore ID/IDREF errors */ + protected static final String ID_IDREF_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore unparsed entity errors */ + protected static final String UNPARSED_ENTITY_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore identity constraint errors */ + protected static final String IDENTITY_CONSTRAINT_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; + /** Feature identifier: namespace growth */ protected static final String NAMESPACE_GROWTH = Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE; @@ -135,6 +148,10 @@ public class StandardParserConfiguration protected static final String SCHEMA_DV_FACTORY = Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY; + /** Property identifier: root type definition. */ + protected static final String ROOT_TYPE_DEF = + Constants.XERCES_PROPERTY_PREFIX + Constants.ROOT_TYPE_DEFINITION_PROPERTY; + // // Data // @@ -211,6 +228,10 @@ public class StandardParserConfiguration // not-recognized exception to be thrown. -Ac XMLSCHEMA_VALIDATION, XMLSCHEMA_FULL_CHECKING, + IGNORE_XSI_TYPE, + ID_IDREF_CHECKING, + IDENTITY_CONSTRAINT_CHECKING, + UNPARSED_ENTITY_CHECKING, }; addRecognizedFeatures(recognizedFeatures); @@ -221,6 +242,10 @@ public class StandardParserConfiguration setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, false); setFeature(VALIDATE_ANNOTATIONS, false); setFeature(HONOUR_ALL_SCHEMALOCATIONS, false); + setFeature(IGNORE_XSI_TYPE, false); + setFeature(ID_IDREF_CHECKING, true); + setFeature(IDENTITY_CONSTRAINT_CHECKING, true); + setFeature(UNPARSED_ENTITY_CHECKING, true); setFeature(NAMESPACE_GROWTH, false); setFeature(TOLERATE_DUPLICATES, false); @@ -233,11 +258,11 @@ public class StandardParserConfiguration // not-recognized exception to be thrown. -Ac SCHEMA_LOCATION, SCHEMA_NONS_LOCATION, + ROOT_TYPE_DEF, SCHEMA_DV_FACTORY, - }; - - addRecognizedProperties(recognizedProperties); + }; + addRecognizedProperties(recognizedProperties); } // (SymbolTable,XMLGrammarPool) // diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java index c0283f74e3c..975367eb2be 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/parsers/XML11Configuration.java @@ -1,13 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -/* - * Copyright 2001-2005 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -184,7 +181,21 @@ public class XML11Configuration extends ParserConfigurationSettings protected static final String EXTERNAL_PARAMETER_ENTITIES = Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE; + /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */ + protected static final String IGNORE_XSI_TYPE = + Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE; + /** Feature identifier: whether to ignore ID/IDREF errors */ + protected static final String ID_IDREF_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore unparsed entity errors */ + protected static final String UNPARSED_ENTITY_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE; + + /** Feature identifier: whether to ignore identity constraint errors */ + protected static final String IDENTITY_CONSTRAINT_CHECKING = + Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE; // property identifiers @@ -267,6 +278,10 @@ public class XML11Configuration extends ParserConfigurationSettings protected static final String JAXP_SCHEMA_SOURCE = Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE; + /** Property identifier: root type definition. */ + protected static final String ROOT_TYPE_DEF = + Constants.XERCES_PROPERTY_PREFIX + Constants.ROOT_TYPE_DEFINITION_PROPERTY; + /** Property identifier: locale. */ protected static final String LOCALE = Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY; @@ -467,25 +482,27 @@ public class XML11Configuration extends ParserConfigurationSettings // add default recognized features final String[] recognizedFeatures = - { - CONTINUE_AFTER_FATAL_ERROR, LOAD_EXTERNAL_DTD, // from XMLDTDScannerImpl - VALIDATION, - NAMESPACES, - NORMALIZE_DATA, SCHEMA_ELEMENT_DEFAULT, SCHEMA_AUGMENT_PSVI, - GENERATE_SYNTHETIC_ANNOTATIONS, VALIDATE_ANNOTATIONS, - HONOUR_ALL_SCHEMALOCATIONS, NAMESPACE_GROWTH, - TOLERATE_DUPLICATES, - USE_GRAMMAR_POOL_ONLY, - // NOTE: These shouldn't really be here but since the XML Schema - // validator is constructed dynamically, its recognized - // features might not have been set and it would cause a - // not-recognized exception to be thrown. -Ac - XMLSCHEMA_VALIDATION, XMLSCHEMA_FULL_CHECKING, - EXTERNAL_GENERAL_ENTITIES, - EXTERNAL_PARAMETER_ENTITIES, - PARSER_SETTINGS, - XMLConstants.FEATURE_SECURE_PROCESSING - }; + { + CONTINUE_AFTER_FATAL_ERROR, LOAD_EXTERNAL_DTD, // from XMLDTDScannerImpl + VALIDATION, + NAMESPACES, + NORMALIZE_DATA, SCHEMA_ELEMENT_DEFAULT, SCHEMA_AUGMENT_PSVI, + GENERATE_SYNTHETIC_ANNOTATIONS, VALIDATE_ANNOTATIONS, + HONOUR_ALL_SCHEMALOCATIONS, IGNORE_XSI_TYPE, + ID_IDREF_CHECKING, IDENTITY_CONSTRAINT_CHECKING, + UNPARSED_ENTITY_CHECKING, + NAMESPACE_GROWTH, TOLERATE_DUPLICATES, + USE_GRAMMAR_POOL_ONLY, + // NOTE: These shouldn't really be here but since the XML Schema + // validator is constructed dynamically, its recognized + // features might not have been set and it would cause a + // not-recognized exception to be thrown. -Ac + XMLSCHEMA_VALIDATION, XMLSCHEMA_FULL_CHECKING, + EXTERNAL_GENERAL_ENTITIES, + EXTERNAL_PARAMETER_ENTITIES, + PARSER_SETTINGS, + XMLConstants.FEATURE_SECURE_PROCESSING + }; addRecognizedFeatures(recognizedFeatures); // set state for default features fFeatures.put(VALIDATION, Boolean.FALSE); @@ -500,6 +517,10 @@ public class XML11Configuration extends ParserConfigurationSettings fFeatures.put(GENERATE_SYNTHETIC_ANNOTATIONS, Boolean.FALSE); fFeatures.put(VALIDATE_ANNOTATIONS, Boolean.FALSE); fFeatures.put(HONOUR_ALL_SCHEMALOCATIONS, Boolean.FALSE); + fFeatures.put(IGNORE_XSI_TYPE, Boolean.FALSE); + fFeatures.put(ID_IDREF_CHECKING, Boolean.TRUE); + fFeatures.put(IDENTITY_CONSTRAINT_CHECKING, Boolean.TRUE); + fFeatures.put(UNPARSED_ENTITY_CHECKING, Boolean.TRUE); fFeatures.put(NAMESPACE_GROWTH, Boolean.FALSE); fFeatures.put(TOLERATE_DUPLICATES, Boolean.FALSE); fFeatures.put(USE_GRAMMAR_POOL_ONLY, Boolean.FALSE); @@ -508,41 +529,42 @@ public class XML11Configuration extends ParserConfigurationSettings // add default recognized properties final String[] recognizedProperties = - { - SYMBOL_TABLE, - ERROR_HANDLER, - ENTITY_RESOLVER, - ERROR_REPORTER, - ENTITY_MANAGER, - DOCUMENT_SCANNER, - DTD_SCANNER, - DTD_PROCESSOR, - DTD_VALIDATOR, - DATATYPE_VALIDATOR_FACTORY, - VALIDATION_MANAGER, - SCHEMA_VALIDATOR, - XML_STRING, - XMLGRAMMAR_POOL, - JAXP_SCHEMA_SOURCE, - JAXP_SCHEMA_LANGUAGE, - // NOTE: These shouldn't really be here but since the XML Schema - // validator is constructed dynamically, its recognized - // properties might not have been set and it would cause a - // not-recognized exception to be thrown. -Ac - SCHEMA_LOCATION, - SCHEMA_NONS_LOCATION, - LOCALE, - SCHEMA_DV_FACTORY, - SECURITY_MANAGER, - XML_SECURITY_PROPERTY_MANAGER + { + SYMBOL_TABLE, + ERROR_HANDLER, + ENTITY_RESOLVER, + ERROR_REPORTER, + ENTITY_MANAGER, + DOCUMENT_SCANNER, + DTD_SCANNER, + DTD_PROCESSOR, + DTD_VALIDATOR, + DATATYPE_VALIDATOR_FACTORY, + VALIDATION_MANAGER, + SCHEMA_VALIDATOR, + XML_STRING, + XMLGRAMMAR_POOL, + JAXP_SCHEMA_SOURCE, + JAXP_SCHEMA_LANGUAGE, + // NOTE: These shouldn't really be here but since the XML Schema + // validator is constructed dynamically, its recognized + // properties might not have been set and it would cause a + // not-recognized exception to be thrown. -Ac + SCHEMA_LOCATION, + SCHEMA_NONS_LOCATION, + ROOT_TYPE_DEF, + LOCALE, + SCHEMA_DV_FACTORY, + SECURITY_MANAGER, + XML_SECURITY_PROPERTY_MANAGER }; addRecognizedProperties(recognizedProperties); - if (symbolTable == null) { - symbolTable = new SymbolTable(); - } - fSymbolTable = symbolTable; - fProperties.put(SYMBOL_TABLE, fSymbolTable); + if (symbolTable == null) { + symbolTable = new SymbolTable(); + } + fSymbolTable = symbolTable; + fProperties.put(SYMBOL_TABLE, fSymbolTable); fGrammarPool = grammarPool; if (fGrammarPool != null) { @@ -597,8 +619,7 @@ public class XML11Configuration extends ParserConfigurationSettings // REVISIT: What is the right thing to do? -Ac } - fConfigUpdated = false; - + fConfigUpdated = false; } // (SymbolTable,XMLGrammarPool) // diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Catalog.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Catalog.java index a5c0e683825..0e5cb5a3e3f 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Catalog.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Catalog.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// Catalog.java - Represents OASIS Open Catalog files. - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -25,28 +19,24 @@ package com.sun.org.apache.xml.internal.resolver; import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl; import com.sun.org.apache.xerces.internal.utils.SecuritySupport; -import java.io.IOException; -import java.io.FileNotFoundException; -import java.io.InputStream; -import java.io.UnsupportedEncodingException; -import java.io.DataInputStream; - -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -import java.net.URL; -import java.net.MalformedURLException; - -import javax.xml.parsers.SAXParserFactory; - -import com.sun.org.apache.xml.internal.resolver.CatalogManager; +import com.sun.org.apache.xml.internal.resolver.helpers.FileURL; import com.sun.org.apache.xml.internal.resolver.helpers.PublicId; import com.sun.org.apache.xml.internal.resolver.readers.CatalogReader; +import com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader; import com.sun.org.apache.xml.internal.resolver.readers.SAXCatalogReader; import com.sun.org.apache.xml.internal.resolver.readers.TR9401CatalogReader; -import com.sun.org.apache.xml.internal.resolver.readers.OASISXMLCatalogReader; -import com.sun.org.apache.xml.internal.resolver.helpers.FileURL; +import java.io.DataInputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Locale; +import java.util.Vector; +import javax.xml.parsers.SAXParserFactory; /** * Represents OASIS Open Catalog files. @@ -154,8 +144,6 @@ import com.sun.org.apache.xml.internal.resolver.helpers.FileURL; * *

Additional catalogs may also be loaded with the * {@link #parseCatalog} method.

- * - * * *

Change Log:

*
@@ -823,7 +811,7 @@ public class Catalog { catalogCwd = FileURL.makeURL("basename"); } catch (MalformedURLException e) { String userdir = SecuritySupport.getSystemProperty("user.dir"); - userdir.replace('\\', '/'); + userdir = userdir.replace('\\', '/'); catalogManager.debug.message(1, "Malformed URL on cwd", userdir); catalogCwd = null; } @@ -2113,66 +2101,113 @@ public class Catalog { } } - /** - * Perform character normalization on a URI reference. - * - * @param uriref The URI reference - * @return The normalized URI reference. - */ - protected String normalizeURI(String uriref) { - if (uriref == null) { - return null; + + /** + * Perform character normalization on a URI reference. + * + * @param uriref The URI reference + * @return The normalized URI reference. + */ + protected String normalizeURI(String uriref) { + if (uriref == null) { + return null; + } + final int length = uriref.length(); + for (int i = 0; i < length; ++i) { + char c = uriref.charAt(i); + if ((c <= 0x20) // ctrl + || (c > 0x7F) // high ascii + || (c == 0x22) // " + || (c == 0x3C) // < + || (c == 0x3E) // > + || (c == 0x5C) // \ + || (c == 0x5E) // ^ + || (c == 0x60) // ` + || (c == 0x7B) // { + || (c == 0x7C) // | + || (c == 0x7D) // } + || (c == 0x7F)) { + return normalizeURI(uriref, i); + } + } + return uriref; } - byte[] bytes; - try { - bytes = uriref.getBytes("UTF-8"); - } catch (UnsupportedEncodingException uee) { - // this can't happen - catalogManager.debug.message(1, "UTF-8 is an unsupported encoding!?"); - return uriref; + /** + * Perform character normalization on a URI reference. + * + * @param uriref The URI reference + * @param index The index of the first character which requires escaping. + * @return The normalized URI reference. + */ + private String normalizeURI(String uriref, int index) { + final StringBuilder buffer = new StringBuilder(); + for (int i = 0; i < index; ++i) { + buffer.append(uriref.charAt(i)); + } + final byte[] bytes; + try { + bytes = uriref.substring(index).getBytes("UTF-8"); + } + catch (UnsupportedEncodingException uee) { + // this can't happen + catalogManager.debug.message(1, "UTF-8 is an unsupported encoding!?"); + return uriref; + } + for (int count = 0; count < bytes.length; ++count) { + int ch = bytes[count] & 0xFF; + if ((ch <= 0x20) // ctrl + || (ch > 0x7F) // high ascii + || (ch == 0x22) // " + || (ch == 0x3C) // < + || (ch == 0x3E) // > + || (ch == 0x5C) // \ + || (ch == 0x5E) // ^ + || (ch == 0x60) // ` + || (ch == 0x7B) // { + || (ch == 0x7C) // | + || (ch == 0x7D) // } + || (ch == 0x7F)) { + writeEncodedByte(ch, buffer); + } + else { + buffer.append((char) bytes[count]); + } + } + return buffer.toString(); } - StringBuilder newRef = new StringBuilder(bytes.length); - for (int count = 0; count < bytes.length; count++) { - int ch = bytes[count] & 0xFF; - - if ((ch <= 0x20) // ctrl - || (ch > 0x7F) // high ascii - || (ch == 0x22) // " - || (ch == 0x3C) // < - || (ch == 0x3E) // > - || (ch == 0x5C) // \ - || (ch == 0x5E) // ^ - || (ch == 0x60) // ` - || (ch == 0x7B) // { - || (ch == 0x7C) // | - || (ch == 0x7D) // } - || (ch == 0x7F)) { - newRef.append(encodedByte(ch)); - } else { - newRef.append((char) bytes[count]); - } + /** + * Perform %-encoding on a single byte. + * + * @param b The 8-bit integer that represents the byte. (Bytes are signed + * but encoding needs to look at the bytes unsigned.) + * @return The %-encoded string for the byte in question. + */ + protected String encodedByte(int b) { + StringBuilder buffer = new StringBuilder(3); + writeEncodedByte(b, buffer); + return buffer.toString(); } - return newRef.toString(); - } - - /** - * Perform %-encoding on a single byte. - * - * @param b The 8-bit integer that represents th byte. (Bytes are signed - but encoding needs to look at the bytes unsigned.) - * @return The %-encoded string for the byte in question. - */ - protected String encodedByte (int b) { - String hex = Integer.toHexString(b).toUpperCase(); - if (hex.length() < 2) { - return "%0" + hex; - } else { - return "%" + hex; + /** + * Perform %-encoding on a single byte. + * + * @param b The 8-bit integer that represents the byte. (Bytes are signed + * but encoding needs to look at the bytes unsigned.) + * @param buffer The target for the %-encoded string for the byte in question. + */ + private void writeEncodedByte(int b, StringBuilder buffer) { + String hex = Integer.toHexString(b).toUpperCase(Locale.ENGLISH); + if (hex.length() < 2) { + buffer.append("%0"); + buffer.append(hex); + } + else { + buffer.append('%'); + buffer.append(hex); + } } - } // ----------------------------------------------------------------- diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogEntry.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogEntry.java index 076e2f52b98..e90d8faa51c 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogEntry.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogEntry.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// CatalogEntry.java - Represents Catalog entries - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -53,18 +47,18 @@ import java.util.Vector; */ public class CatalogEntry { /** The nextEntry is the ordinal number of the next entry type. */ - protected static int nextEntry = 0; + static int nextEntry = 0; /** * The entryTypes vector maps catalog entry names * (e.g., 'BASE' or 'SYSTEM') to their type (1, 2, etc.). * Names are case sensitive. */ - protected static Hashtable entryTypes = new Hashtable(); + static final Hashtable entryTypes = new Hashtable(); /** The entryTypes vector maps catalog entry types to the number of arguments they're required to have. */ - protected static Vector entryArgs = new Vector(); + static final Vector entryArgs = new Vector(); /** * Adds a new catalog entry type. diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogException.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogException.java index c0b5404376c..1fc92db135b 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogException.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogException.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// CatalogException.java - Catalog exception - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -36,6 +30,9 @@ package com.sun.org.apache.xml.internal.resolver; * */ public class CatalogException extends Exception { + + private static final long serialVersionUID = 4007157171817798450L; + /** A wrapper around another exception */ public static final int WRAPPER = 1; /** An invalid entry */ @@ -56,8 +53,8 @@ public class CatalogException extends Exception { /** * The embedded exception if tunnelling, or null. */ - private Exception exception = null; - private int exceptionType = 0; + private final Exception exception; + private final int exceptionType; /** * Create a new CatalogException. diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogManager.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogManager.java index ab8cd27c647..b5fccbf04aa 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogManager.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/CatalogManager.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// CatalogManager.java - Access CatalogManager.properties - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -124,78 +118,78 @@ import sun.reflect.misc.ReflectUtil; */ public class CatalogManager { - private static String pFiles = "xml.catalog.files"; - private static String pVerbosity = "xml.catalog.verbosity"; - private static String pPrefer = "xml.catalog.prefer"; - private static String pStatic = "xml.catalog.staticCatalog"; - private static String pAllowPI = "xml.catalog.allowPI"; - private static String pClassname = "xml.catalog.className"; - private static String pIgnoreMissing = "xml.catalog.ignoreMissing"; + private static final String pFiles = "xml.catalog.files"; + private static final String pVerbosity = "xml.catalog.verbosity"; + private static final String pPrefer = "xml.catalog.prefer"; + private static final String pStatic = "xml.catalog.staticCatalog"; + private static final String pAllowPI = "xml.catalog.allowPI"; + private static final String pClassname = "xml.catalog.className"; + private static final String pIgnoreMissing = "xml.catalog.ignoreMissing"; - /** A static CatalogManager instance for sharing */ - private static CatalogManager staticManager = new CatalogManager(); + /** A static CatalogManager instance for sharing */ + private static final CatalogManager staticManager = new CatalogManager(); - /** The bootstrap resolver to use when loading XML Catalogs. */ - private BootstrapResolver bResolver = new BootstrapResolver(); + /** The bootstrap resolver to use when loading XML Catalogs. */ + private BootstrapResolver bResolver = new BootstrapResolver(); - /** Flag to ignore missing property files and/or properties */ - private boolean ignoreMissingProperties + /** Flag to ignore missing property files and/or properties */ + private boolean ignoreMissingProperties = (SecuritySupport.getSystemProperty(pIgnoreMissing) != null - || SecuritySupport.getSystemProperty(pFiles) != null); + || SecuritySupport.getSystemProperty(pFiles) != null); - /** Holds the resources after they are loaded from the file. */ - private ResourceBundle resources; + /** Holds the resources after they are loaded from the file. */ + private ResourceBundle resources; - /** The name of the CatalogManager properties file. */ - private String propertyFile = "CatalogManager.properties"; + /** The name of the CatalogManager properties file. */ + private String propertyFile = "CatalogManager.properties"; - /** The location of the propertyFile */ - private URL propertyFileURI = null; + /** The location of the propertyFile */ + private URL propertyFileURI = null; - /** Default catalog files list. */ - private String defaultCatalogFiles = "./xcatalog"; + /** Default catalog files list. */ + private String defaultCatalogFiles = "./xcatalog"; - /** Current catalog files list. */ - private String catalogFiles = null; + /** Current catalog files list. */ + private String catalogFiles = null; - /** Did the catalogFiles come from the properties file? */ - private boolean fromPropertiesFile = false; + /** Did the catalogFiles come from the properties file? */ + private boolean fromPropertiesFile = false; - /** Default verbosity level if there is no property setting for it. */ - private int defaultVerbosity = 1; + /** Default verbosity level if there is no property setting for it. */ + private int defaultVerbosity = 1; - /** Current verbosity level. */ - private Integer verbosity = null; + /** Current verbosity level. */ + private Integer verbosity = null; - /** Default preference setting. */ - private boolean defaultPreferPublic = true; + /** Default preference setting. */ + private boolean defaultPreferPublic = true; - /** Current preference setting. */ - private Boolean preferPublic = null; + /** Current preference setting. */ + private Boolean preferPublic = null; - /** Default setting of the static catalog flag. */ - private boolean defaultUseStaticCatalog = true; + /** Default setting of the static catalog flag. */ + private boolean defaultUseStaticCatalog = true; - /** Current setting of the static catalog flag. */ - private Boolean useStaticCatalog = null; + /** Current setting of the static catalog flag. */ + private Boolean useStaticCatalog = null; - /** The static catalog used by this manager. */ - private static Catalog staticCatalog = null; + /** The static catalog used by this manager. */ + private static volatile Catalog staticCatalog = null; - /** Default setting of the oasisXMLCatalogPI flag. */ - private boolean defaultOasisXMLCatalogPI = true; + /** Default setting of the oasisXMLCatalogPI flag. */ + private boolean defaultOasisXMLCatalogPI = true; - /** Current setting of the oasisXMLCatalogPI flag. */ - private Boolean oasisXMLCatalogPI = null; + /** Current setting of the oasisXMLCatalogPI flag. */ + private Boolean oasisXMLCatalogPI = null; - /** Default setting of the relativeCatalogs flag. */ - private boolean defaultRelativeCatalogs = true; + /** Default setting of the relativeCatalogs flag. */ + private boolean defaultRelativeCatalogs = true; - /** Current setting of the relativeCatalogs flag. */ - private Boolean relativeCatalogs = null; + /** Current setting of the relativeCatalogs flag. */ + private Boolean relativeCatalogs = null; - /** Current catalog class name. */ - private String catalogClassName = null; + /** Current catalog class name. */ + private String catalogClassName = null; /** * Indicates whether implementation parts should use * service loader (or similar). @@ -203,26 +197,26 @@ public class CatalogManager { */ private boolean useServicesMechanism; - /** The manager's debug object. Used for printing debugging messages. - * - *

This field is public so that objects that have access to this - * CatalogManager can use this debug object.

- */ - public Debug debug = null; + /** The manager's debug object. Used for printing debugging messages. + * + *

This field is public so that objects that have access to this + * CatalogManager can use this debug object.

+ */ + public Debug debug = null; - /** Constructor. */ - public CatalogManager() { - init(); - } + /** Constructor. */ + public CatalogManager() { + init(); + } - /** Constructor that specifies an explicit property file. */ - public CatalogManager(String propertyFile) { - this.propertyFile = propertyFile; - init(); + /** Constructor that specifies an explicit property file. */ + public CatalogManager(String propertyFile) { + this.propertyFile = propertyFile; + init(); } private void init() { - debug = new Debug(); + debug = new Debug(); // Note that we don't setDebug() here; we do that lazily. Either the // user will set it explicitly, or we'll do it automagically if they // read from the propertyFile for some other reason. That way, there's @@ -231,616 +225,638 @@ public class CatalogManager { if (System.getSecurityManager() == null) { useServicesMechanism = true; } - } - /** Set the bootstrap resolver.*/ - public void setBootstrapResolver(BootstrapResolver resolver) { - bResolver = resolver; - } + // Make sure verbosity is set by xml.catalog.verbosity sysprop + // setting, if defined. + queryVerbosityFromSysProp(); + } - /** Get the bootstrap resolver.*/ - public BootstrapResolver getBootstrapResolver() { - return bResolver; - } + /** Set the bootstrap resolver + * @param resolver the bootstrap resolver + */ + public void setBootstrapResolver(BootstrapResolver resolver) { + bResolver = resolver; + } - /** - * Load the properties from the propertyFile and build the - * resources from it. - */ - private synchronized void readProperties() { - try { - propertyFileURI = CatalogManager.class.getResource("/"+propertyFile); - InputStream in = - CatalogManager.class.getResourceAsStream("/"+propertyFile); - if (in==null) { - if (!ignoreMissingProperties) { - System.err.println("Cannot find "+propertyFile); - // there's no reason to give this warning more than once - ignoreMissingProperties = true; + /** Get the bootstrap resolver + * @return the bootstrap resolver + */ + public BootstrapResolver getBootstrapResolver() { + return bResolver; + } + + /** Query system property for verbosity level. */ + private void queryVerbosityFromSysProp() { + String verbStr = SecuritySupport.getSystemProperty(pVerbosity); + if (verbStr != null) { + try { + int verb = Integer.parseInt(verbStr.trim()); + verbosity = new Integer(verb); + debug.setDebug(verb); + } catch (Exception e) { + System.err.println("Cannot parse verbosity: \"" + verbStr + "\""); + } } - return; - } - resources = new PropertyResourceBundle(in); - } catch (MissingResourceException mre) { - if (!ignoreMissingProperties) { - System.err.println("Cannot read "+propertyFile); - } - } catch (java.io.IOException e) { - if (!ignoreMissingProperties) { - System.err.println("Failure trying to read "+propertyFile); - } } - // This is a bit of a hack. After we've successfully read the properties, - // use them to set the default debug level, if the user hasn't already set - // the default debug level. - if (verbosity == null) { - try { - String verbStr = resources.getString("verbosity"); - int verb = Integer.parseInt(verbStr.trim()); - debug.setDebug(verb); - verbosity = new Integer(verb); - } catch (Exception e) { - // nop - } - } - } - - /** - * Allow access to the static CatalogManager - */ - public static CatalogManager getStaticManager() { - return staticManager; - } - - /** - * How are missing properties handled? - * - *

If true, missing or unreadable property files will - * not be reported. Otherwise, a message will be sent to System.err. - *

- */ - public boolean getIgnoreMissingProperties() { - return ignoreMissingProperties; - } - - /** - * How should missing properties be handled? - * - *

If ignore is true, missing or unreadable property files will - * not be reported. Otherwise, a message will be sent to System.err. - *

- */ - public void setIgnoreMissingProperties(boolean ignore) { - ignoreMissingProperties = ignore; - } - - /** - * How are missing properties handled? - * - *

If ignore is true, missing or unreadable property files will - * not be reported. Otherwise, a message will be sent to System.err. - *

- * - * @deprecated No longer static; use get/set methods. - */ - public void ignoreMissingProperties(boolean ignore) { - setIgnoreMissingProperties(ignore); - } - - /** - * Obtain the verbosity setting from the properties. - * - * @return The verbosity level from the propertyFile or the - * defaultVerbosity. - */ - private int queryVerbosity () { - String defaultVerbStr = Integer.toString(defaultVerbosity); - - String verbStr = SecuritySupport.getSystemProperty(pVerbosity); - - if (verbStr == null) { - if (resources==null) readProperties(); - if (resources != null) { + /** + * Load the properties from the propertyFile and build the + * resources from it. + */ + private synchronized void readProperties() { try { - verbStr = resources.getString("verbosity"); + propertyFileURI = CatalogManager.class.getResource("/"+propertyFile); + InputStream in = + CatalogManager.class.getResourceAsStream("/"+propertyFile); + if (in==null) { + if (!ignoreMissingProperties) { + System.err.println("Cannot find "+propertyFile); + // there's no reason to give this warning more than once + ignoreMissingProperties = true; + } + return; + } + resources = new PropertyResourceBundle(in); + } catch (MissingResourceException mre) { + if (!ignoreMissingProperties) { + System.err.println("Cannot read "+propertyFile); + } + } catch (java.io.IOException e) { + if (!ignoreMissingProperties) { + System.err.println("Failure trying to read "+propertyFile); + } + } + + // This is a bit of a hack. After we've successfully read the properties, + // use them to set the default debug level, if the user hasn't already set + // the default debug level. + if (verbosity == null) { + try { + String verbStr = resources.getString("verbosity"); + int verb = Integer.parseInt(verbStr.trim()); + debug.setDebug(verb); + verbosity = new Integer(verb); + } catch (Exception e) { + // nop + } + } + } + + /** + * Allow access to the static CatalogManager + */ + public static CatalogManager getStaticManager() { + return staticManager; + } + + /** + * How are missing properties handled? + * + *

If true, missing or unreadable property files will + * not be reported. Otherwise, a message will be sent to System.err. + *

+ */ + public boolean getIgnoreMissingProperties() { + return ignoreMissingProperties; + } + + /** + * How should missing properties be handled? + * + *

If ignore is true, missing or unreadable property files will + * not be reported. Otherwise, a message will be sent to System.err. + *

+ */ + public void setIgnoreMissingProperties(boolean ignore) { + ignoreMissingProperties = ignore; + } + + /** + * How are missing properties handled? + * + *

If ignore is true, missing or unreadable property files will + * not be reported. Otherwise, a message will be sent to System.err. + *

+ * + * @deprecated No longer static; use get/set methods. + */ + public void ignoreMissingProperties(boolean ignore) { + setIgnoreMissingProperties(ignore); + } + + /** + * Obtain the verbosity setting from the properties. + * + * @return The verbosity level from the propertyFile or the + * defaultVerbosity. + */ + private int queryVerbosity () { + String defaultVerbStr = Integer.toString(defaultVerbosity); + + String verbStr = SecuritySupport.getSystemProperty(pVerbosity); + + if (verbStr == null) { + if (resources==null) readProperties(); + if (resources != null) { + try { + verbStr = resources.getString("verbosity"); + } catch (MissingResourceException e) { + verbStr = defaultVerbStr; + } + } else { + verbStr = defaultVerbStr; + } + } + + int verb = defaultVerbosity; + + try { + verb = Integer.parseInt(verbStr.trim()); + } catch (Exception e) { + System.err.println("Cannot parse verbosity: \"" + verbStr + "\""); + } + + // This is a bit of a hack. After we've successfully got the verbosity, + // we have to use it to set the default debug level, + // if the user hasn't already set the default debug level. + if (verbosity == null) { + debug.setDebug(verb); + verbosity = new Integer(verb); + } + + return verb; + } + + /** + * What is the current verbosity? + */ + public int getVerbosity() { + if (verbosity == null) { + verbosity = new Integer(queryVerbosity()); + } + + return verbosity.intValue(); + } + + /** + * Set the current verbosity. + */ + public void setVerbosity (int verbosity) { + this.verbosity = new Integer(verbosity); + debug.setDebug(verbosity); + } + + /** + * What is the current verbosity? + * + * @deprecated No longer static; use get/set methods. + */ + public int verbosity () { + return getVerbosity(); + } + + /** + * Obtain the relativeCatalogs setting from the properties. + * + * @return The relativeCatalogs setting from the propertyFile or the + * defaultRelativeCatalogs. + */ + private boolean queryRelativeCatalogs () { + if (resources==null) readProperties(); + + if (resources==null) return defaultRelativeCatalogs; + + try { + String allow = resources.getString("relative-catalogs"); + return (allow.equalsIgnoreCase("true") + || allow.equalsIgnoreCase("yes") + || allow.equalsIgnoreCase("1")); } catch (MissingResourceException e) { - verbStr = defaultVerbStr; + return defaultRelativeCatalogs; } - } else { - verbStr = defaultVerbStr; - } } - int verb = defaultVerbosity; - - try { - verb = Integer.parseInt(verbStr.trim()); - } catch (Exception e) { - System.err.println("Cannot parse verbosity: \"" + verbStr + "\""); - } - - // This is a bit of a hack. After we've successfully got the verbosity, - // we have to use it to set the default debug level, - // if the user hasn't already set the default debug level. - if (verbosity == null) { - debug.setDebug(verb); - verbosity = new Integer(verb); - } - - return verb; - } - - /** - * What is the current verbosity? - */ - public int getVerbosity() { - if (verbosity == null) { - verbosity = new Integer(queryVerbosity()); - } - - return verbosity.intValue(); - } - - /** - * Set the current verbosity. - */ - public void setVerbosity (int verbosity) { - this.verbosity = new Integer(verbosity); - debug.setDebug(verbosity); - } - - /** - * What is the current verbosity? - * - * @deprecated No longer static; use get/set methods. - */ - public int verbosity () { - return getVerbosity(); - } - - /** - * Obtain the relativeCatalogs setting from the properties. - * - * @return The relativeCatalogs setting from the propertyFile or the - * defaultRelativeCatalogs. - */ - private boolean queryRelativeCatalogs () { - if (resources==null) readProperties(); - - if (resources==null) return defaultRelativeCatalogs; - - try { - String allow = resources.getString("relative-catalogs"); - return (allow.equalsIgnoreCase("true") - || allow.equalsIgnoreCase("yes") - || allow.equalsIgnoreCase("1")); - } catch (MissingResourceException e) { - return defaultRelativeCatalogs; - } - } - - /** - * Get the relativeCatalogs setting. - * - *

This property is used when the catalogFiles property is - * interrogated. If true, then relative catalog entry file names - * are returned. If false, relative catalog entry file names are - * made absolute with respect to the properties file before returning - * them.

- * - *

This property only applies when the catalog files - * come from a properties file. If they come from a system property or - * the default list, they are never considered relative. (What would - * they be relative to?)

- * - *

In the properties, a value of 'yes', 'true', or '1' is considered - * true, anything else is false.

- * - * @return The relativeCatalogs setting from the propertyFile or the - * defaultRelativeCatalogs. - */ - public boolean getRelativeCatalogs () { - if (relativeCatalogs == null) { - relativeCatalogs = new Boolean(queryRelativeCatalogs()); - } - - return relativeCatalogs.booleanValue(); - } - - /** - * Set the relativeCatalogs setting. - * - * @see #getRelativeCatalogs() - */ - public void setRelativeCatalogs (boolean relative) { - relativeCatalogs = new Boolean(relative); - } - - /** - * Get the relativeCatalogs setting. - * - * @deprecated No longer static; use get/set methods. - */ - public boolean relativeCatalogs () { - return getRelativeCatalogs(); - } - - /** - * Obtain the list of catalog files from the properties. - * - * @return A semicolon delimited list of catlog file URIs - */ - private String queryCatalogFiles () { - String catalogList = SecuritySupport.getSystemProperty(pFiles); - fromPropertiesFile = false; - - if (catalogList == null) { - if (resources == null) readProperties(); - if (resources != null) { - try { - catalogList = resources.getString("catalogs"); - fromPropertiesFile = true; - } catch (MissingResourceException e) { - System.err.println(propertyFile + ": catalogs not found."); - catalogList = null; + /** + * Get the relativeCatalogs setting. + * + *

This property is used when the catalogFiles property is + * interrogated. If true, then relative catalog entry file names + * are returned. If false, relative catalog entry file names are + * made absolute with respect to the properties file before returning + * them.

+ * + *

This property only applies when the catalog files + * come from a properties file. If they come from a system property or + * the default list, they are never considered relative. (What would + * they be relative to?)

+ * + *

In the properties, a value of 'yes', 'true', or '1' is considered + * true, anything else is false.

+ * + * @return The relativeCatalogs setting from the propertyFile or the + * defaultRelativeCatalogs. + */ + public boolean getRelativeCatalogs () { + if (relativeCatalogs == null) { + relativeCatalogs = queryRelativeCatalogs() ? Boolean.TRUE : Boolean.FALSE; } - } + + return relativeCatalogs.booleanValue(); } - if (catalogList == null) { - catalogList = defaultCatalogFiles; + /** + * Set the relativeCatalogs setting. + * + * @see #getRelativeCatalogs() + */ + public void setRelativeCatalogs (boolean relative) { + relativeCatalogs = relative ? Boolean.TRUE : Boolean.FALSE; } - return catalogList; - } - - /** - * Return the current list of catalog files. - * - * @return A vector of the catalog file names or null if no catalogs - * are available in the properties. - */ - public Vector getCatalogFiles() { - if (catalogFiles == null) { - catalogFiles = queryCatalogFiles(); + /** + * Get the relativeCatalogs setting. + * + * @deprecated No longer static; use get/set methods. + */ + public boolean relativeCatalogs () { + return getRelativeCatalogs(); } - StringTokenizer files = new StringTokenizer(catalogFiles, ";"); - Vector catalogs = new Vector(); - while (files.hasMoreTokens()) { - String catalogFile = files.nextToken(); - URL absURI = null; + /** + * Obtain the list of catalog files from the properties. + * + * @return A semicolon delimited list of catlog file URIs + */ + private String queryCatalogFiles () { + String catalogList = SecuritySupport.getSystemProperty(pFiles); + fromPropertiesFile = false; - if (fromPropertiesFile && !relativeCatalogs()) { - try { - absURI = new URL(propertyFileURI, catalogFile); - catalogFile = absURI.toString(); - } catch (MalformedURLException mue) { - absURI = null; + if (catalogList == null) { + if (resources == null) readProperties(); + if (resources != null) { + try { + catalogList = resources.getString("catalogs"); + fromPropertiesFile = true; + } catch (MissingResourceException e) { + System.err.println(propertyFile + ": catalogs not found."); + catalogList = null; + } + } } - } - catalogs.add(catalogFile); + if (catalogList == null) { + catalogList = defaultCatalogFiles; + } + + return catalogList; } - return catalogs; - } + /** + * Return the current list of catalog files. + * + * @return A vector of the catalog file names or null if no catalogs + * are available in the properties. + */ + public Vector getCatalogFiles() { + if (catalogFiles == null) { + catalogFiles = queryCatalogFiles(); + } - /** - * Set the list of catalog files. - */ - public void setCatalogFiles(String fileList) { - catalogFiles = fileList; - fromPropertiesFile = false; - } + StringTokenizer files = new StringTokenizer(catalogFiles, ";"); + Vector catalogs = new Vector(); + while (files.hasMoreTokens()) { + String catalogFile = files.nextToken(); + URL absURI = null; - /** - * Return the current list of catalog files. - * - * @return A vector of the catalog file names or null if no catalogs - * are available in the properties. - * - * @deprecated No longer static; use get/set methods. - */ - public Vector catalogFiles() { - return getCatalogFiles(); - } + if (fromPropertiesFile && !relativeCatalogs()) { + try { + absURI = new URL(propertyFileURI, catalogFile); + catalogFile = absURI.toString(); + } catch (MalformedURLException mue) { + absURI = null; + } + } - /** - * Obtain the preferPublic setting from the properties. - * - *

In the properties, a value of 'public' is true, - * anything else is false.

- * - * @return True if prefer is public or the - * defaultPreferSetting. - */ - private boolean queryPreferPublic () { - String prefer = SecuritySupport.getSystemProperty(pPrefer); + catalogs.add(catalogFile); + } - if (prefer == null) { - if (resources==null) readProperties(); - if (resources==null) return defaultPreferPublic; - try { - prefer = resources.getString("prefer"); - } catch (MissingResourceException e) { - return defaultPreferPublic; - } + return catalogs; } - if (prefer == null) { - return defaultPreferPublic; + /** + * Set the list of catalog files. + */ + public void setCatalogFiles(String fileList) { + catalogFiles = fileList; + fromPropertiesFile = false; } - return (prefer.equalsIgnoreCase("public")); - } - - /** - * Return the current prefer public setting. - * - * @return True if public identifiers are preferred. - */ - public boolean getPreferPublic () { - if (preferPublic == null) { - preferPublic = new Boolean(queryPreferPublic()); - } - return preferPublic.booleanValue(); - } - - /** - * Set the prefer public setting. - */ - public void setPreferPublic (boolean preferPublic) { - this.preferPublic = new Boolean(preferPublic); - } - - /** - * Return the current prefer public setting. - * - * @return True if public identifiers are preferred. - * - * @deprecated No longer static; use get/set methods. - */ - public boolean preferPublic () { - return getPreferPublic(); - } - - /** - * Obtain the static-catalog setting from the properties. - * - *

In the properties, a value of 'yes', 'true', or '1' is considered - * true, anything else is false.

- * - * @return The static-catalog setting from the propertyFile or the - * defaultUseStaticCatalog. - */ - private boolean queryUseStaticCatalog () { - String staticCatalog = SecuritySupport.getSystemProperty(pStatic); - - if (staticCatalog == null) { - if (resources==null) readProperties(); - if (resources==null) return defaultUseStaticCatalog; - try { - staticCatalog = resources.getString("static-catalog"); - } catch (MissingResourceException e) { - return defaultUseStaticCatalog; - } + /** + * Return the current list of catalog files. + * + * @return A vector of the catalog file names or null if no catalogs + * are available in the properties. + * + * @deprecated No longer static; use get/set methods. + */ + public Vector catalogFiles() { + return getCatalogFiles(); } - if (staticCatalog == null) { - return defaultUseStaticCatalog; + /** + * Obtain the preferPublic setting from the properties. + * + *

In the properties, a value of 'public' is true, + * anything else is false.

+ * + * @return True if prefer is public or the + * defaultPreferSetting. + */ + private boolean queryPreferPublic () { + String prefer = SecuritySupport.getSystemProperty(pPrefer); + + if (prefer == null) { + if (resources==null) readProperties(); + if (resources==null) return defaultPreferPublic; + try { + prefer = resources.getString("prefer"); + } catch (MissingResourceException e) { + return defaultPreferPublic; + } + } + + if (prefer == null) { + return defaultPreferPublic; + } + + return (prefer.equalsIgnoreCase("public")); } - return (staticCatalog.equalsIgnoreCase("true") - || staticCatalog.equalsIgnoreCase("yes") - || staticCatalog.equalsIgnoreCase("1")); - } - - /** - * Get the current use static catalog setting. - */ - public boolean getUseStaticCatalog() { - if (useStaticCatalog == null) { - useStaticCatalog = new Boolean(queryUseStaticCatalog()); + /** + * Return the current prefer public setting. + * + * @return True if public identifiers are preferred. + */ + public boolean getPreferPublic () { + if (preferPublic == null) { + preferPublic = queryPreferPublic() ? Boolean.TRUE : Boolean.FALSE; + } + return preferPublic.booleanValue(); } - return useStaticCatalog.booleanValue(); - } - - /** - * Set the use static catalog setting. - */ - public void setUseStaticCatalog(boolean useStatic) { - useStaticCatalog = new Boolean(useStatic); - } - - /** - * Get the current use static catalog setting. - * - * @deprecated No longer static; use get/set methods. - */ - public boolean staticCatalog() { - return getUseStaticCatalog(); - } - - /** - * Get a new catalog instance. - * - * This method always returns a new instance of the underlying catalog class. - */ - public Catalog getPrivateCatalog() { - Catalog catalog = staticCatalog; - - if (useStaticCatalog == null) { - useStaticCatalog = new Boolean(getUseStaticCatalog()); + /** + * Set the prefer public setting. + */ + public void setPreferPublic (boolean preferPublic) { + this.preferPublic = preferPublic ? Boolean.TRUE : Boolean.FALSE; } - if (catalog == null || !useStaticCatalog.booleanValue()) { + /** + * Return the current prefer public setting. + * + * @return True if public identifiers are preferred. + * + * @deprecated No longer static; use get/set methods. + */ + public boolean preferPublic () { + return getPreferPublic(); + } - try { - String catalogClassName = getCatalogClassName(); + /** + * Obtain the static-catalog setting from the properties. + * + *

In the properties, a value of 'yes', 'true', or '1' is considered + * true, anything else is false.

+ * + * @return The static-catalog setting from the propertyFile or the + * defaultUseStaticCatalog. + */ + private boolean queryUseStaticCatalog () { + String staticCatalog = SecuritySupport.getSystemProperty(pStatic); + if (staticCatalog == null) { + if (resources==null) readProperties(); + if (resources==null) return defaultUseStaticCatalog; + try { + staticCatalog = resources.getString("static-catalog"); + } catch (MissingResourceException e) { + return defaultUseStaticCatalog; + } + } + + if (staticCatalog == null) { + return defaultUseStaticCatalog; + } + + return (staticCatalog.equalsIgnoreCase("true") + || staticCatalog.equalsIgnoreCase("yes") + || staticCatalog.equalsIgnoreCase("1")); + } + + /** + * Get the current use static catalog setting. + */ + public boolean getUseStaticCatalog() { + if (useStaticCatalog == null) { + useStaticCatalog = queryUseStaticCatalog() ? Boolean.TRUE : Boolean.FALSE; + } + + return useStaticCatalog.booleanValue(); + } + + /** + * Set the use static catalog setting. + */ + public void setUseStaticCatalog(boolean useStatic) { + useStaticCatalog = useStatic ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Get the current use static catalog setting. + * + * @deprecated No longer static; use get/set methods. + */ + public boolean staticCatalog() { + return getUseStaticCatalog(); + } + + /** + * Get a new catalog instance. + * + * This method always returns a new instance of the underlying catalog class. + */ + public Catalog getPrivateCatalog() { + Catalog catalog = staticCatalog; + + if (useStaticCatalog == null) { + useStaticCatalog = getUseStaticCatalog() ? Boolean.TRUE : Boolean.FALSE; + } + + if (catalog == null || !useStaticCatalog.booleanValue()) { + + try { + String catalogClassName = getCatalogClassName(); + + if (catalogClassName == null) { + catalog = new Catalog(); + } else { + try { + catalog = (Catalog) ReflectUtil.forName(catalogClassName).newInstance(); + } catch (ClassNotFoundException cnfe) { + debug.message(1,"Catalog class named '" + + catalogClassName + + "' could not be found. Using default."); + catalog = new Catalog(); + } catch (ClassCastException cnfe) { + debug.message(1,"Class named '" + + catalogClassName + + "' is not a Catalog. Using default."); + catalog = new Catalog(); + } + } + + catalog.setCatalogManager(this); + catalog.setupReaders(); + catalog.loadSystemCatalogs(); + } catch (Exception ex) { + ex.printStackTrace(); + } + + if (useStaticCatalog.booleanValue()) { + staticCatalog = catalog; + } + } + + return catalog; + } + + /** + * Get a catalog instance. + * + * If this manager uses static catalogs, the same static catalog will + * always be returned. Otherwise a new catalog will be returned. + */ + public Catalog getCatalog() { + Catalog catalog = staticCatalog; + + if (useStaticCatalog == null) { + useStaticCatalog = getUseStaticCatalog() ? Boolean.TRUE : Boolean.FALSE; + } + + if (catalog == null || !useStaticCatalog.booleanValue()) { + catalog = getPrivateCatalog(); + if (useStaticCatalog.booleanValue()) { + staticCatalog = catalog; + } + } + + return catalog; + } + + /** + *

Obtain the oasisXMLCatalogPI setting from the properties.

+ * + *

In the properties, a value of 'yes', 'true', or '1' is considered + * true, anything else is false.

+ * + * @return The oasisXMLCatalogPI setting from the propertyFile or the + * defaultOasisXMLCatalogPI. + */ + public boolean queryAllowOasisXMLCatalogPI () { + String allow = SecuritySupport.getSystemProperty(pAllowPI); + + if (allow == null) { + if (resources==null) readProperties(); + if (resources==null) return defaultOasisXMLCatalogPI; + try { + allow = resources.getString("allow-oasis-xml-catalog-pi"); + } catch (MissingResourceException e) { + return defaultOasisXMLCatalogPI; + } + } + + if (allow == null) { + return defaultOasisXMLCatalogPI; + } + + return (allow.equalsIgnoreCase("true") + || allow.equalsIgnoreCase("yes") + || allow.equalsIgnoreCase("1")); + } + + /** + * Get the current XML Catalog PI setting. + */ + public boolean getAllowOasisXMLCatalogPI () { + if (oasisXMLCatalogPI == null) { + oasisXMLCatalogPI = queryAllowOasisXMLCatalogPI() ? Boolean.TRUE : Boolean.FALSE; + } + + return oasisXMLCatalogPI.booleanValue(); + } + + public boolean useServicesMechanism() { + return useServicesMechanism; + } + /** + * Set the XML Catalog PI setting + */ + public void setAllowOasisXMLCatalogPI(boolean allowPI) { + oasisXMLCatalogPI = allowPI ? Boolean.TRUE : Boolean.FALSE; + } + + /** + * Get the current XML Catalog PI setting. + * + * @deprecated No longer static; use get/set methods. + */ + public boolean allowOasisXMLCatalogPI() { + return getAllowOasisXMLCatalogPI(); + } + + /** + * Obtain the Catalog class name setting from the properties. + * + */ + public String queryCatalogClassName () { + String className = SecuritySupport.getSystemProperty(pClassname); + + if (className == null) { + if (resources==null) readProperties(); + if (resources==null) return null; + try { + return resources.getString("catalog-class-name"); + } catch (MissingResourceException e) { + return null; + } + } + + return className; + } + + /** + * Get the current Catalog class name. + */ + public String getCatalogClassName() { if (catalogClassName == null) { - catalog = new Catalog(); - } else { - try { - catalog = (Catalog) ReflectUtil.forName(catalogClassName).newInstance(); - } catch (ClassNotFoundException cnfe) { - debug.message(1,"Catalog class named '" - + catalogClassName - + "' could not be found. Using default."); - catalog = new Catalog(); - } catch (ClassCastException cnfe) { - debug.message(1,"Class named '" - + catalogClassName - + "' is not a Catalog. Using default."); - catalog = new Catalog(); - } + catalogClassName = queryCatalogClassName(); } - catalog.setCatalogManager(this); - catalog.setupReaders(); - catalog.loadSystemCatalogs(); - } catch (Exception ex) { - ex.printStackTrace(); - } - - if (useStaticCatalog.booleanValue()) { - staticCatalog = catalog; - } + return catalogClassName; } - return catalog; - } - - /** - * Get a catalog instance. - * - * If this manager uses static catalogs, the same static catalog will - * always be returned. Otherwise a new catalog will be returned. - */ - public Catalog getCatalog() { - Catalog catalog = staticCatalog; - - if (useStaticCatalog == null) { - useStaticCatalog = new Boolean(getUseStaticCatalog()); + /** + * Set the Catalog class name. + */ + public void setCatalogClassName(String className) { + catalogClassName = className; } - if (catalog == null || !useStaticCatalog.booleanValue()) { - catalog = getPrivateCatalog(); - if (useStaticCatalog.booleanValue()) { - staticCatalog = catalog; - } + /** + * Get the current Catalog class name. + * + * @deprecated No longer static; use get/set methods. + */ + public String catalogClassName() { + return getCatalogClassName(); } - - return catalog; - } - - /** - *

Obtain the oasisXMLCatalogPI setting from the properties.

- * - *

In the properties, a value of 'yes', 'true', or '1' is considered - * true, anything else is false.

- * - * @return The oasisXMLCatalogPI setting from the propertyFile or the - * defaultOasisXMLCatalogPI. - */ - public boolean queryAllowOasisXMLCatalogPI () { - String allow = SecuritySupport.getSystemProperty(pAllowPI); - - if (allow == null) { - if (resources==null) readProperties(); - if (resources==null) return defaultOasisXMLCatalogPI; - try { - allow = resources.getString("allow-oasis-xml-catalog-pi"); - } catch (MissingResourceException e) { - return defaultOasisXMLCatalogPI; - } - } - - if (allow == null) { - return defaultOasisXMLCatalogPI; - } - - return (allow.equalsIgnoreCase("true") - || allow.equalsIgnoreCase("yes") - || allow.equalsIgnoreCase("1")); - } - - /** - * Get the current XML Catalog PI setting. - */ - public boolean getAllowOasisXMLCatalogPI () { - if (oasisXMLCatalogPI == null) { - oasisXMLCatalogPI = new Boolean(queryAllowOasisXMLCatalogPI()); - } - - return oasisXMLCatalogPI.booleanValue(); - } - - public boolean useServicesMechanism() { - return useServicesMechanism; - } - /** - * Set the XML Catalog PI setting - */ - public void setAllowOasisXMLCatalogPI(boolean allowPI) { - oasisXMLCatalogPI = new Boolean(allowPI); - } - - /** - * Get the current XML Catalog PI setting. - * - * @deprecated No longer static; use get/set methods. - */ - public boolean allowOasisXMLCatalogPI() { - return getAllowOasisXMLCatalogPI(); - } - - /** - * Obtain the Catalog class name setting from the properties. - * - */ - public String queryCatalogClassName () { - String className = SecuritySupport.getSystemProperty(pClassname); - - if (className == null) { - if (resources==null) readProperties(); - if (resources==null) return null; - try { - return resources.getString("catalog-class-name"); - } catch (MissingResourceException e) { - return null; - } - } - - return className; - } - - /** - * Get the current Catalog class name. - */ - public String getCatalogClassName() { - if (catalogClassName == null) { - catalogClassName = queryCatalogClassName(); - } - - return catalogClassName; - } - - /** - * Set the Catalog class name. - */ - public void setCatalogClassName(String className) { - catalogClassName = className; - } - - /** - * Get the current Catalog class name. - * - * @deprecated No longer static; use get/set methods. - */ - public String catalogClassName() { - return getCatalogClassName(); - } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Resolver.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Resolver.java index 721d67c8d4e..d566895ccce 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Resolver.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/Resolver.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// Resolver.java - Represents an extension of OASIS Open Catalog files. - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -94,7 +88,7 @@ public class Resolver extends Catalog { SAXCatalogReader saxReader = new SAXCatalogReader(spf); - saxReader.setCatalogParser(null, "XMLCatalog", + saxReader.setCatalogParser(null, "XCatalog", "com.sun.org.apache.xml.internal.resolver.readers.XCatalogReader"); saxReader.setCatalogParser(OASISXMLCatalogReader.namespaceName, diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/BootstrapResolver.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/BootstrapResolver.java index 9d5df419b6a..5bdf3d8e94a 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/BootstrapResolver.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/BootstrapResolver.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// BootstrapResolver.java - Resolve entities and URIs internally - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -65,14 +59,17 @@ public class BootstrapResolver implements EntityResolver, URIResolver { /** System identifier for OASIS XML Catalog files. */ public static final String xmlCatalogSysId = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd"; + /** Public identifier for legacy Apache XCatalog files. There is no official system identifier for XCatalog files. */ + public static final String xCatalogPubId = "-//DTD XCatalog//EN"; + /** Private hash used for public identifiers. */ - private Hashtable publicMap = new Hashtable(); + private final Hashtable publicMap = new Hashtable(); /** Private hash used for system identifiers. */ - private Hashtable systemMap = new Hashtable(); + private final Hashtable systemMap = new Hashtable(); /** Private hash used for URIs. */ - private Hashtable uriMap = new Hashtable(); + private final Hashtable uriMap = new Hashtable(); /** Constructor. */ public BootstrapResolver() { @@ -91,6 +88,11 @@ public class BootstrapResolver implements EntityResolver, URIResolver { if (url != null) { uriMap.put(xmlCatalogXSD, url.toString()); } + + url = this.getClass().getResource("/com/sun/org/apache/xml/internal/resolver/etc/xcatalog.dtd"); + if (url != null) { + publicMap.put(xCatalogPubId, url.toString()); + } } /** SAX resolveEntity API. */ diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Debug.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Debug.java index fbf2b8f2674..6a6c03a48e5 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Debug.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Debug.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// Debug.java - Print debug messages - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/FileURL.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/FileURL.java index e5a5605323e..6717739005a 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/FileURL.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/FileURL.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// FileURL.java - Construct a file: scheme URL - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Namespaces.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Namespaces.java index 02624a61615..6511cf26224 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Namespaces.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/Namespaces.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// Namespaces.java - Analyze namespace nodes in a DOM tree - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -47,8 +41,9 @@ public class Namespaces { String name = element.getTagName(); String prefix = ""; - if (name.indexOf(':') > 0) { - prefix = name.substring(0, name.indexOf(':')); + final int indexOfColon = name.indexOf(':'); + if (indexOfColon > 0) { + prefix = name.substring(0, indexOfColon); } return prefix; @@ -64,8 +59,9 @@ public class Namespaces { public static String getLocalName(Element element) { String name = element.getTagName(); - if (name.indexOf(':') > 0) { - name = name.substring(name.indexOf(':')+1); + final int indexOfColon = name.indexOf(':'); + if (indexOfColon > 0) { + name = name.substring(indexOfColon + 1); } return name; @@ -85,7 +81,7 @@ public class Namespaces { return null; } - if (prefix.equals("")) { + if (prefix.length() == 0) { if (((Element) node).hasAttribute("xmlns")) { return ((Element) node).getAttribute("xmlns"); } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/PublicId.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/PublicId.java index 8211a770db5..d70f4f034ac 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/PublicId.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/helpers/PublicId.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// PublicId.java - Information about public identifiers - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -34,7 +28,8 @@ package com.sun.org.apache.xml.internal.resolver.helpers; * */ public abstract class PublicId { - protected PublicId() { } + + protected PublicId() {} /** * Normalize a public identifier. @@ -58,18 +53,17 @@ public abstract class PublicId { * @return The normalized identifier. */ public static String normalize(String publicId) { - String normal = publicId.replace('\t', ' '); - normal = normal.replace('\r', ' '); - normal = normal.replace('\n', ' '); - normal = normal.trim(); + String normal = publicId.replace('\t', ' '); + normal = normal.replace('\r', ' '); + normal = normal.replace('\n', ' '); + normal = normal.trim(); - int pos; + int pos; - while ((pos = normal.indexOf(" ")) >= 0) { - normal = normal.substring(0, pos) + normal.substring(pos+1); - } - - return normal; + while ((pos = normal.indexOf(" ")) >= 0) { + normal = normal.substring(0, pos) + normal.substring(pos+1); + } + return normal; } /** @@ -83,21 +77,24 @@ public abstract class PublicId { * @return The normalized identifier. */ public static String encodeURN(String publicId) { - String urn = PublicId.normalize(publicId); + String urn = PublicId.normalize(publicId); - urn = PublicId.stringReplace(urn, "%", "%25"); - urn = PublicId.stringReplace(urn, ";", "%3B"); - urn = PublicId.stringReplace(urn, "'", "%27"); - urn = PublicId.stringReplace(urn, "?", "%3F"); - urn = PublicId.stringReplace(urn, "#", "%23"); - urn = PublicId.stringReplace(urn, "+", "%2B"); - urn = PublicId.stringReplace(urn, " ", "+"); - urn = PublicId.stringReplace(urn, "::", ";"); - urn = PublicId.stringReplace(urn, ":", "%3A"); - urn = PublicId.stringReplace(urn, "//", ":"); - urn = PublicId.stringReplace(urn, "/", "%2F"); + urn = PublicId.stringReplace(urn, "%", "%25"); + urn = PublicId.stringReplace(urn, ";", "%3B"); + urn = PublicId.stringReplace(urn, "'", "%27"); + urn = PublicId.stringReplace(urn, "?", "%3F"); + urn = PublicId.stringReplace(urn, "#", "%23"); + urn = PublicId.stringReplace(urn, "+", "%2B"); + urn = PublicId.stringReplace(urn, " ", "+"); + urn = PublicId.stringReplace(urn, "::", ";"); + urn = PublicId.stringReplace(urn, ":", "%3A"); + urn = PublicId.stringReplace(urn, "//", ":"); + urn = PublicId.stringReplace(urn, "/", "%2F"); - return "urn:publicid:" + urn; + StringBuilder buffer = new StringBuilder(13 + urn.length()); + buffer.append("urn:publicid:"); + buffer.append(urn); + return buffer.toString(); } /** @@ -111,51 +108,62 @@ public abstract class PublicId { * @return The normalized identifier. */ public static String decodeURN(String urn) { - String publicId = ""; + String publicId; + if (urn.startsWith("urn:publicid:")) { + publicId = urn.substring(13); + } + else { + return urn; + } - if (urn.startsWith("urn:publicid:")) { - publicId = urn.substring(13); - } else { - return urn; - } + final boolean hasEscape = (publicId.indexOf('%') >= 0); + if (hasEscape) { + publicId = PublicId.stringReplace(publicId, "%2F", "/"); + } + publicId = PublicId.stringReplace(publicId, ":", "//"); + if (hasEscape) { + publicId = PublicId.stringReplace(publicId, "%3A", ":"); + } + publicId = PublicId.stringReplace(publicId, ";", "::"); + publicId = PublicId.stringReplace(publicId, "+", " "); + if (hasEscape) { + publicId = PublicId.stringReplace(publicId, "%2B", "+"); + publicId = PublicId.stringReplace(publicId, "%23", "#"); + publicId = PublicId.stringReplace(publicId, "%3F", "?"); + publicId = PublicId.stringReplace(publicId, "%27", "'"); + publicId = PublicId.stringReplace(publicId, "%3B", ";"); + publicId = PublicId.stringReplace(publicId, "%25", "%"); + } - publicId = PublicId.stringReplace(publicId, "%2F", "/"); - publicId = PublicId.stringReplace(publicId, ":", "//"); - publicId = PublicId.stringReplace(publicId, "%3A", ":"); - publicId = PublicId.stringReplace(publicId, ";", "::"); - publicId = PublicId.stringReplace(publicId, "+", " "); - publicId = PublicId.stringReplace(publicId, "%2B", "+"); - publicId = PublicId.stringReplace(publicId, "%23", "#"); - publicId = PublicId.stringReplace(publicId, "%3F", "?"); - publicId = PublicId.stringReplace(publicId, "%27", "'"); - publicId = PublicId.stringReplace(publicId, "%3B", ";"); - publicId = PublicId.stringReplace(publicId, "%25", "%"); - - return publicId; - } + return publicId; + } /** * Replace one string with another. - * */ private static String stringReplace(String str, - String oldStr, - String newStr) { - - String result = ""; - int pos = str.indexOf(oldStr); - - // System.out.println(str + ": " + oldStr + " => " + newStr); - - while (pos >= 0) { - // System.out.println(str + " (" + pos + ")"); - result += str.substring(0, pos); - result += newStr; - str = str.substring(pos+1); - - pos = str.indexOf(oldStr); - } - - return result + str; + String oldStr, + String newStr) { + int pos = str.indexOf(oldStr); + if (pos >= 0) { + final StringBuilder buffer = new StringBuilder(); + final int oldStrLength = oldStr.length(); + int start = 0; + do { + for (int i = start; i < pos; ++i) { + buffer.append(str.charAt(i)); + } + buffer.append(newStr); + start = pos + oldStrLength; + pos = str.indexOf(oldStr, start); + } + while (pos >= 0); + final int strLength = str.length(); + for (int i = start; i < strLength; ++i) { + buffer.append(str.charAt(i)); + } + return buffer.toString(); + } + return str; } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/CatalogReader.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/CatalogReader.java index cc8bd09f2cb..444b38769dc 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/CatalogReader.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/CatalogReader.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// CatalogReader.java - An interface for reading catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogParser.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogParser.java index ff4af953946..c0e34011ab0 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogParser.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogParser.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// DOMCatalogParser.java - An interface for reading catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java index bd14b28ae39..22d131fe0f7 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/DOMCatalogReader.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// DOMCatalogReader.java - Read XML Catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/ExtendedXMLCatalogReader.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/ExtendedXMLCatalogReader.java index a638a4757e4..2fd0dc6b1e2 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/ExtendedXMLCatalogReader.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/ExtendedXMLCatalogReader.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// ExtendedXMLCatalogReader.java - Read XML Catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -166,7 +160,7 @@ public class ExtendedXMLCatalogReader extends OASISXMLCatalogReader { String baseURI = (String) baseURIStack.peek(); if (!baseURI.equals(popURI)) { - entryType = catalog.BASE; + entryType = Catalog.BASE; entryArgs.add(baseURI); debug.message(4, "(reset) xml:base", baseURI); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/OASISXMLCatalogReader.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/OASISXMLCatalogReader.java index f1d6b8983b5..04ddf623199 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/OASISXMLCatalogReader.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/OASISXMLCatalogReader.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// OASISXMLCatalogReader.java - Read XML Catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -23,16 +17,16 @@ package com.sun.org.apache.xml.internal.resolver.readers; -import java.util.Stack; -import java.util.Vector; -import java.util.Enumeration; import com.sun.org.apache.xml.internal.resolver.Catalog; import com.sun.org.apache.xml.internal.resolver.CatalogEntry; import com.sun.org.apache.xml.internal.resolver.CatalogException; import com.sun.org.apache.xml.internal.resolver.helpers.PublicId; - -import org.xml.sax.*; +import java.util.Enumeration; +import java.util.Stack; +import java.util.Vector; +import javax.xml.parsers.SAXParserFactory; import org.w3c.dom.*; +import org.xml.sax.*; /** * Parse OASIS Entity Resolution Technical Committee @@ -71,6 +65,17 @@ public class OASISXMLCatalogReader extends SAXCatalogReader implements SAXCatalo return catalog; } + /** Default constructor */ + public OASISXMLCatalogReader() { + super(); + } + + /** Constructor allowing for providing custom SAX parser factory */ + public OASISXMLCatalogReader(SAXParserFactory parserFactory, Catalog catalog) { + super(parserFactory); + setCatalog(catalog); + } + /** * Are we in an extension namespace? * @@ -102,7 +107,7 @@ public class OASISXMLCatalogReader extends SAXCatalogReader implements SAXCatalo return; } - /** The SAX startDocument method does nothing. */ + /** The SAX startDocument */ public void startDocument () throws SAXException { baseURIStack.push(catalog.getCurrentBase()); @@ -371,14 +376,14 @@ public class OASISXMLCatalogReader extends SAXCatalogReader implements SAXCatalo } if (localName.equals("doctype")) { - entryType = catalog.DOCTYPE; + entryType = Catalog.DOCTYPE; entryArgs.add(atts.getValue("name")); entryArgs.add(atts.getValue("uri")); } else if (localName.equals("document")) { - entryType = catalog.DOCUMENT; + entryType = Catalog.DOCUMENT; entryArgs.add(atts.getValue("uri")); } else if (localName.equals("dtddecl")) { - entryType = catalog.DTDDECL; + entryType = Catalog.DTDDECL; entryArgs.add(atts.getValue("publicId")); entryArgs.add(atts.getValue("uri")); } else if (localName.equals("entity")) { @@ -432,7 +437,7 @@ public class OASISXMLCatalogReader extends SAXCatalogReader implements SAXCatalo && checkAttributes(atts, attName2); } - /** The SAX endElement method does nothing. */ + /** The SAX endElement */ public void endElement (String namespaceURI, String localName, String qName) @@ -452,7 +457,7 @@ public class OASISXMLCatalogReader extends SAXCatalogReader implements SAXCatalo String baseURI = (String) baseURIStack.peek(); if (!baseURI.equals(popURI)) { - entryType = catalog.BASE; + entryType = Catalog.BASE; entryArgs.add(baseURI); debug.message(4, "(reset) xml:base", baseURI); @@ -477,7 +482,7 @@ public class OASISXMLCatalogReader extends SAXCatalogReader implements SAXCatalo String override = (String) overrideStack.peek(); if (!override.equals(popOverride)) { - entryType = catalog.OVERRIDE; + entryType = Catalog.OVERRIDE; entryArgs.add(override); overrideStack.push(override); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogParser.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogParser.java index 782744bc5ee..b70f7dc64fe 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogParser.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogParser.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// SAXCatalogParser.java - An interface for reading catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogReader.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogReader.java index 105cb7671ae..d5d5d2aca27 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogReader.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXCatalogReader.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// SAXCatalogReader.java - Read XML Catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -77,427 +71,423 @@ import sun.reflect.misc.ReflectUtil; * */ public class SAXCatalogReader implements CatalogReader, ContentHandler, DocumentHandler { - /** The SAX Parser Factory */ - protected SAXParserFactory parserFactory = null; + /** The SAX Parser Factory */ + protected SAXParserFactory parserFactory = null; - /** The SAX Parser Class */ - protected String parserClass = null; + /** The SAX Parser Class */ + protected String parserClass = null; - /** + /** * Mapping table from QNames to CatalogParser classes. * *

Each key in this hash table has the form "elementname" * or "{namespaceuri}elementname". The former is used if the * namespace URI is null.

*/ - protected Hashtable namespaceMap = new Hashtable(); + protected Hashtable namespaceMap = new Hashtable(); - /** The parser in use for the current catalog. */ - private SAXCatalogParser saxParser = null; + /** The parser in use for the current catalog. */ + private SAXCatalogParser saxParser = null; - /** Set if something goes horribly wrong. It allows the class to + /** Set if something goes horribly wrong. It allows the class to * ignore the rest of the events that are received. */ - private boolean abandonHope = false; + private boolean abandonHope = false; - /** The Catalog that we're working for. */ - private Catalog catalog; + /** The Catalog that we're working for. */ + private Catalog catalog; - /** Set the XML SAX Parser Factory. - */ - public void setParserFactory(SAXParserFactory parserFactory) { - this.parserFactory = parserFactory; - } + /** Set the XML SAX Parser Factory. + */ + public void setParserFactory(SAXParserFactory parserFactory) { + this.parserFactory = parserFactory; + } - /** Set the XML SAX Parser Class - */ - public void setParserClass(String parserClass) { - this.parserClass = parserClass; - } + /** Set the XML SAX Parser Class + */ + public void setParserClass(String parserClass) { + this.parserClass = parserClass; + } - /** Get the parser factory currently in use. */ - public SAXParserFactory getParserFactory() { - return parserFactory; - } + /** Get the parser factory currently in use. */ + public SAXParserFactory getParserFactory() { + return parserFactory; + } - /** Get the parser class currently in use. */ - public String getParserClass() { - return parserClass; - } + /** Get the parser class currently in use. */ + public String getParserClass() { + return parserClass; + } - /** The debug class to use for this reader. - * - * This is a bit of a hack. Anyway, whenever we read for a catalog, - * we extract the debug object - * from the catalog's manager so that we can use it to print messages. - * - * In production, we don't really expect any messages so it doesn't - * really matter. But it's still a bit of a hack. - */ - protected Debug debug = CatalogManager.getStaticManager().debug; + /** The debug class to use for this reader. + * + * This is a bit of a hack. Anyway, whenever we read for a catalog, + * we extract the debug object + * from the catalog's manager so that we can use it to print messages. + * + * In production, we don't really expect any messages so it doesn't + * really matter. But it's still a bit of a hack. + */ + protected Debug debug = CatalogManager.getStaticManager().debug; - /** The constructor */ - public SAXCatalogReader() { - parserFactory = null; - parserClass = null; - } + /** The constructor */ + public SAXCatalogReader() { + parserFactory = null; + parserClass = null; + } - /** The constructor */ - public SAXCatalogReader(SAXParserFactory parserFactory) { - this.parserFactory = parserFactory; - } + /** The constructor */ + public SAXCatalogReader(SAXParserFactory parserFactory) { + this.parserFactory = parserFactory; + } - /** The constructor */ - public SAXCatalogReader(String parserClass) { - this.parserClass = parserClass; - } + /** The constructor */ + public SAXCatalogReader(String parserClass) { + this.parserClass = parserClass; + } - /** Set the SAXCatalogParser class for the given namespace/root + /** + * Set the SAXCatalogParser class for the given namespace/root * element type. */ - public void setCatalogParser(String namespaceURI, - String rootElement, - String parserClass) { - if (namespaceURI == null) { - namespaceMap.put(rootElement, parserClass); - } else { - namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass); + public void setCatalogParser(String namespaceURI, + String rootElement, + String parserClass) { + namespaceURI = namespaceURI != null ? namespaceURI.trim() : ""; + namespaceMap.put("{"+namespaceURI+"}"+rootElement, parserClass); } - } - /** Get the SAXCatalogParser class for the given namespace/root + /** + * Get the SAXCatalogParser class for the given namespace/root * element type. */ - public String getCatalogParser(String namespaceURI, - String rootElement) { - if (namespaceURI == null) { - return (String) namespaceMap.get(rootElement); - } else { - return (String) namespaceMap.get("{"+namespaceURI+"}"+rootElement); - } - } - - /** - * Parse an XML Catalog file. - * - * @param catalog The catalog to which this catalog file belongs - * @param fileUrl The URL or filename of the catalog file to process - * - * @throws MalformedURLException Improper fileUrl - * @throws IOException Error reading catalog file - */ - public void readCatalog(Catalog catalog, String fileUrl) - throws MalformedURLException, IOException, - CatalogException { - - URL url = null; - - try { - url = new URL(fileUrl); - } catch (MalformedURLException e) { - url = new URL("file:///" + fileUrl); + public String getCatalogParser(String namespaceURI, + String rootElement) { + namespaceURI = namespaceURI != null ? namespaceURI.trim() : ""; + return (String) namespaceMap.get("{"+namespaceURI+"}"+rootElement); } - debug = catalog.getCatalogManager().debug; + /** + * Parse an XML Catalog file. + * + * @param catalog The catalog to which this catalog file belongs + * @param fileUrl The URL or filename of the catalog file to process + * + * @throws MalformedURLException Improper fileUrl + * @throws IOException Error reading catalog file + */ + public void readCatalog(Catalog catalog, String fileUrl) + throws MalformedURLException, IOException, + CatalogException { - try { - URLConnection urlCon = url.openConnection(); - readCatalog(catalog, urlCon.getInputStream()); - } catch (FileNotFoundException e) { - catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found", + URL url = null; + + try { + url = new URL(fileUrl); + } catch (MalformedURLException e) { + url = new URL("file:///" + fileUrl); + } + + debug = catalog.getCatalogManager().debug; + + try { + URLConnection urlCon = url.openConnection(); + readCatalog(catalog, urlCon.getInputStream()); + } catch (FileNotFoundException e) { + catalog.getCatalogManager().debug.message(1, "Failed to load catalog, file not found", url.toString()); - } - } - - /** - * Parse an XML Catalog stream. - * - * @param catalog The catalog to which this catalog file belongs - * @param is The input stream from which the catalog will be read - * - * @throws MalformedURLException Improper fileUrl - * @throws IOException Error reading catalog file - * @throws CatalogException A Catalog exception - */ - public void readCatalog(Catalog catalog, InputStream is) - throws IOException, CatalogException { - - // Create an instance of the parser - if (parserFactory == null && parserClass == null) { - debug.message(1, "Cannot read SAX catalog without a parser"); - throw new CatalogException(CatalogException.UNPARSEABLE); - } - - debug = catalog.getCatalogManager().debug; - EntityResolver bResolver = catalog.getCatalogManager().getBootstrapResolver(); - - this.catalog = catalog; - - try { - if (parserFactory != null) { - SAXParser parser = parserFactory.newSAXParser(); - SAXParserHandler spHandler = new SAXParserHandler(); - spHandler.setContentHandler(this); - if (bResolver != null) { - spHandler.setEntityResolver(bResolver); } - parser.parse(new InputSource(is), spHandler); - } else { - Parser parser = (Parser) ReflectUtil.forName(parserClass).newInstance(); - parser.setDocumentHandler(this); - if (bResolver != null) { - parser.setEntityResolver(bResolver); + } + + /** + * Parse an XML Catalog stream. + * + * @param catalog The catalog to which this catalog file belongs + * @param is The input stream from which the catalog will be read + * + * @throws MalformedURLException Improper fileUrl + * @throws IOException Error reading catalog file + * @throws CatalogException A Catalog exception + */ + public void readCatalog(Catalog catalog, InputStream is) + throws IOException, CatalogException { + + // Create an instance of the parser + if (parserFactory == null && parserClass == null) { + debug.message(1, "Cannot read SAX catalog without a parser"); + throw new CatalogException(CatalogException.UNPARSEABLE); } - parser.parse(new InputSource(is)); - } - } catch (ClassNotFoundException cnfe) { - throw new CatalogException(CatalogException.UNPARSEABLE); - } catch (IllegalAccessException iae) { - throw new CatalogException(CatalogException.UNPARSEABLE); - } catch (InstantiationException ie) { - throw new CatalogException(CatalogException.UNPARSEABLE); - } catch (ParserConfigurationException pce) { - throw new CatalogException(CatalogException.UNKNOWN_FORMAT); - } catch (SAXException se) { - Exception e = se.getException(); - // FIXME: there must be a better way - UnknownHostException uhe = new UnknownHostException(); - FileNotFoundException fnfe = new FileNotFoundException(); - if (e != null) { - if (e.getClass() == uhe.getClass()) { - throw new CatalogException(CatalogException.PARSE_FAILED, - e.toString()); - } else if (e.getClass() == fnfe.getClass()) { - throw new CatalogException(CatalogException.PARSE_FAILED, - e.toString()); + + debug = catalog.getCatalogManager().debug; + EntityResolver bResolver = catalog.getCatalogManager().getBootstrapResolver(); + + this.catalog = catalog; + + try { + if (parserFactory != null) { + SAXParser parser = parserFactory.newSAXParser(); + SAXParserHandler spHandler = new SAXParserHandler(); + spHandler.setContentHandler(this); + if (bResolver != null) { + spHandler.setEntityResolver(bResolver); + } + parser.parse(new InputSource(is), spHandler); + } else { + Parser parser = (Parser) ReflectUtil.forName(parserClass).newInstance(); + parser.setDocumentHandler(this); + if (bResolver != null) { + parser.setEntityResolver(bResolver); + } + parser.parse(new InputSource(is)); + } + } catch (ClassNotFoundException cnfe) { + throw new CatalogException(CatalogException.UNPARSEABLE); + } catch (IllegalAccessException iae) { + throw new CatalogException(CatalogException.UNPARSEABLE); + } catch (InstantiationException ie) { + throw new CatalogException(CatalogException.UNPARSEABLE); + } catch (ParserConfigurationException pce) { + throw new CatalogException(CatalogException.UNKNOWN_FORMAT); + } catch (SAXException se) { + Exception e = se.getException(); + // FIXME: there must be a better way + UnknownHostException uhe = new UnknownHostException(); + FileNotFoundException fnfe = new FileNotFoundException(); + if (e != null) { + if (e.getClass() == uhe.getClass()) { + throw new CatalogException(CatalogException.PARSE_FAILED, + e.toString()); + } else if (e.getClass() == fnfe.getClass()) { + throw new CatalogException(CatalogException.PARSE_FAILED, + e.toString()); + } + } + throw new CatalogException(se); } - } - throw new CatalogException(se); - } - } - - // ---------------------------------------------------------------------- - // Implement the SAX ContentHandler interface - - /** The SAX setDocumentLocator method. Does nothing. */ - public void setDocumentLocator (Locator locator) { - if (saxParser != null) { - saxParser.setDocumentLocator(locator); - } - } - - /** The SAX startDocument method. Does nothing. */ - public void startDocument () throws SAXException { - saxParser = null; - abandonHope = false; - return; - } - - /** The SAX endDocument method. Does nothing. */ - public void endDocument ()throws SAXException { - if (saxParser != null) { - saxParser.endDocument(); - } - } - - /** - * The SAX startElement method. - * - *

The catalog parser is selected based on the namespace of the - * first element encountered in the catalog.

- */ - public void startElement (String name, - AttributeList atts) - throws SAXException { - - if (abandonHope) { - return; } - if (saxParser == null) { - String prefix = ""; - if (name.indexOf(':') > 0) { - prefix = name.substring(0, name.indexOf(':')); - } + // ---------------------------------------------------------------------- + // Implement the SAX ContentHandler interface - String localName = name; - if (localName.indexOf(':') > 0) { - localName = localName.substring(localName.indexOf(':')+1); - } - - String namespaceURI = null; - if (prefix.equals("")) { - namespaceURI = atts.getValue("xmlns"); - } else { - namespaceURI = atts.getValue("xmlns:" + prefix); - } - - String saxParserClass = getCatalogParser(namespaceURI, - localName); - - if (saxParserClass == null) { - abandonHope = true; - if (namespaceURI == null) { - debug.message(2, "No Catalog parser for " + name); - } else { - debug.message(2, "No Catalog parser for " - + "{" + namespaceURI + "}" - + name); + /** The SAX setDocumentLocator method. Does nothing. */ + public void setDocumentLocator (Locator locator) { + if (saxParser != null) { + saxParser.setDocumentLocator(locator); } + } + + /** The SAX startDocument method. Does nothing. */ + public void startDocument () throws SAXException { + saxParser = null; + abandonHope = false; return; - } - - try { - saxParser = (SAXCatalogParser) - ReflectUtil.forName(saxParserClass).newInstance(); - - saxParser.setCatalog(catalog); - saxParser.startDocument(); - saxParser.startElement(name, atts); - } catch (ClassNotFoundException cnfe) { - saxParser = null; - abandonHope = true; - debug.message(2, cnfe.toString()); - } catch (InstantiationException ie) { - saxParser = null; - abandonHope = true; - debug.message(2, ie.toString()); - } catch (IllegalAccessException iae) { - saxParser = null; - abandonHope = true; - debug.message(2, iae.toString()); - } catch (ClassCastException cce ) { - saxParser = null; - abandonHope = true; - debug.message(2, cce.toString()); - } - } else { - saxParser.startElement(name, atts); - } - } - - /** - * The SAX2 startElement method. - * - *

The catalog parser is selected based on the namespace of the - * first element encountered in the catalog.

- */ - public void startElement (String namespaceURI, - String localName, - String qName, - Attributes atts) - throws SAXException { - - if (abandonHope) { - return; } - if (saxParser == null) { - String saxParserClass = getCatalogParser(namespaceURI, - localName); - - if (saxParserClass == null) { - abandonHope = true; - if (namespaceURI == null) { - debug.message(2, "No Catalog parser for " + localName); - } else { - debug.message(2, "No Catalog parser for " - + "{" + namespaceURI + "}" - + localName); + /** The SAX endDocument method. Does nothing. */ + public void endDocument ()throws SAXException { + if (saxParser != null) { + saxParser.endDocument(); } - return; - } - - try { - saxParser = (SAXCatalogParser) - ReflectUtil.forName(saxParserClass).newInstance(); - - saxParser.setCatalog(catalog); - saxParser.startDocument(); - saxParser.startElement(namespaceURI, localName, qName, atts); - } catch (ClassNotFoundException cnfe) { - saxParser = null; - abandonHope = true; - debug.message(2, cnfe.toString()); - } catch (InstantiationException ie) { - saxParser = null; - abandonHope = true; - debug.message(2, ie.toString()); - } catch (IllegalAccessException iae) { - saxParser = null; - abandonHope = true; - debug.message(2, iae.toString()); - } catch (ClassCastException cce ) { - saxParser = null; - abandonHope = true; - debug.message(2, cce.toString()); - } - } else { - saxParser.startElement(namespaceURI, localName, qName, atts); } - } - /** The SAX endElement method. Does nothing. */ - public void endElement (String name) throws SAXException { - if (saxParser != null) { - saxParser.endElement(name); - } - } + /** + * The SAX startElement method. + * + *

The catalog parser is selected based on the namespace of the + * first element encountered in the catalog.

+ */ + public void startElement (String name, + AttributeList atts) + throws SAXException { - /** The SAX2 endElement method. Does nothing. */ - public void endElement (String namespaceURI, - String localName, - String qName) throws SAXException { - if (saxParser != null) { - saxParser.endElement(namespaceURI, localName, qName); - } - } + if (abandonHope) { + return; + } - /** The SAX characters method. Does nothing. */ - public void characters (char ch[], int start, int length) - throws SAXException { - if (saxParser != null) { - saxParser.characters(ch, start, length); - } - } + if (saxParser == null) { + String prefix = ""; + if (name.indexOf(':') > 0) { + prefix = name.substring(0, name.indexOf(':')); + } - /** The SAX ignorableWhitespace method. Does nothing. */ - public void ignorableWhitespace (char ch[], int start, int length) - throws SAXException { - if (saxParser != null) { - saxParser.ignorableWhitespace(ch, start, length); - } - } + String localName = name; + if (localName.indexOf(':') > 0) { + localName = localName.substring(localName.indexOf(':')+1); + } - /** The SAX processingInstruction method. Does nothing. */ - public void processingInstruction (String target, String data) - throws SAXException { - if (saxParser != null) { - saxParser.processingInstruction(target, data); - } - } + String namespaceURI = null; + if (prefix.length() == 0) { + namespaceURI = atts.getValue("xmlns"); + } else { + namespaceURI = atts.getValue("xmlns:" + prefix); + } - /** The SAX startPrefixMapping method. Does nothing. */ - public void startPrefixMapping (String prefix, String uri) - throws SAXException { - if (saxParser != null) { - saxParser.startPrefixMapping (prefix, uri); - } - } + String saxParserClass = getCatalogParser(namespaceURI, + localName); - /** The SAX endPrefixMapping method. Does nothing. */ - public void endPrefixMapping (String prefix) - throws SAXException { - if (saxParser != null) { - saxParser.endPrefixMapping (prefix); - } - } + if (saxParserClass == null) { + abandonHope = true; + if (namespaceURI == null) { + debug.message(2, "No Catalog parser for " + name); + } else { + debug.message(2, "No Catalog parser for " + + "{" + namespaceURI + "}" + + name); + } + return; + } - /** The SAX skippedentity method. Does nothing. */ - public void skippedEntity (String name) - throws SAXException { - if (saxParser != null) { - saxParser.skippedEntity(name); + try { + saxParser = (SAXCatalogParser) + ReflectUtil.forName(saxParserClass).newInstance(); + + saxParser.setCatalog(catalog); + saxParser.startDocument(); + saxParser.startElement(name, atts); + } catch (ClassNotFoundException cnfe) { + saxParser = null; + abandonHope = true; + debug.message(2, cnfe.toString()); + } catch (InstantiationException ie) { + saxParser = null; + abandonHope = true; + debug.message(2, ie.toString()); + } catch (IllegalAccessException iae) { + saxParser = null; + abandonHope = true; + debug.message(2, iae.toString()); + } catch (ClassCastException cce ) { + saxParser = null; + abandonHope = true; + debug.message(2, cce.toString()); + } + } else { + saxParser.startElement(name, atts); + } + } + + /** + * The SAX2 startElement method. + * + *

The catalog parser is selected based on the namespace of the + * first element encountered in the catalog.

+ */ + public void startElement (String namespaceURI, + String localName, + String qName, + Attributes atts) + throws SAXException { + + if (abandonHope) { + return; + } + + if (saxParser == null) { + String saxParserClass = getCatalogParser(namespaceURI, + localName); + + if (saxParserClass == null) { + abandonHope = true; + if (namespaceURI == null) { + debug.message(2, "No Catalog parser for " + localName); + } else { + debug.message(2, "No Catalog parser for " + + "{" + namespaceURI + "}" + + localName); + } + return; + } + + try { + saxParser = (SAXCatalogParser) + ReflectUtil.forName(saxParserClass).newInstance(); + + saxParser.setCatalog(catalog); + saxParser.startDocument(); + saxParser.startElement(namespaceURI, localName, qName, atts); + } catch (ClassNotFoundException cnfe) { + saxParser = null; + abandonHope = true; + debug.message(2, cnfe.toString()); + } catch (InstantiationException ie) { + saxParser = null; + abandonHope = true; + debug.message(2, ie.toString()); + } catch (IllegalAccessException iae) { + saxParser = null; + abandonHope = true; + debug.message(2, iae.toString()); + } catch (ClassCastException cce ) { + saxParser = null; + abandonHope = true; + debug.message(2, cce.toString()); + } + } else { + saxParser.startElement(namespaceURI, localName, qName, atts); + } + } + + /** The SAX endElement method. Does nothing. */ + public void endElement (String name) throws SAXException { + if (saxParser != null) { + saxParser.endElement(name); + } + } + + /** The SAX2 endElement method. Does nothing. */ + public void endElement (String namespaceURI, + String localName, + String qName) throws SAXException { + if (saxParser != null) { + saxParser.endElement(namespaceURI, localName, qName); + } + } + + /** The SAX characters method. Does nothing. */ + public void characters (char ch[], int start, int length) + throws SAXException { + if (saxParser != null) { + saxParser.characters(ch, start, length); + } + } + + /** The SAX ignorableWhitespace method. Does nothing. */ + public void ignorableWhitespace (char ch[], int start, int length) + throws SAXException { + if (saxParser != null) { + saxParser.ignorableWhitespace(ch, start, length); + } + } + + /** The SAX processingInstruction method. Does nothing. */ + public void processingInstruction (String target, String data) + throws SAXException { + if (saxParser != null) { + saxParser.processingInstruction(target, data); + } + } + + /** The SAX startPrefixMapping method. Does nothing. */ + public void startPrefixMapping (String prefix, String uri) + throws SAXException { + if (saxParser != null) { + saxParser.startPrefixMapping (prefix, uri); + } + } + + /** The SAX endPrefixMapping method. Does nothing. */ + public void endPrefixMapping (String prefix) + throws SAXException { + if (saxParser != null) { + saxParser.endPrefixMapping (prefix); + } + } + + /** The SAX skippedentity method. Does nothing. */ + public void skippedEntity (String name) + throws SAXException { + if (saxParser != null) { + saxParser.skippedEntity(name); + } } - } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXParserHandler.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXParserHandler.java index 0d07510aafb..efcf32950df 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXParserHandler.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/SAXParserHandler.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// SAXParserHandler.java - An entity-resolving DefaultHandler - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TR9401CatalogReader.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TR9401CatalogReader.java index b27481049f6..fb39a433063 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TR9401CatalogReader.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TR9401CatalogReader.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// TR9401CatalogReader.java - Read OASIS Catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -23,13 +17,14 @@ package com.sun.org.apache.xml.internal.resolver.readers; -import java.io.InputStream; -import java.io.IOException; -import java.net.MalformedURLException; -import java.util.Vector; import com.sun.org.apache.xml.internal.resolver.Catalog; import com.sun.org.apache.xml.internal.resolver.CatalogEntry; import com.sun.org.apache.xml.internal.resolver.CatalogException; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.util.Locale; +import java.util.Vector; /** * Parses OASIS Open Catalog files. @@ -97,7 +92,7 @@ public class TR9401CatalogReader extends TextCatalogReader { if (caseSensitive) { entryToken = token; } else { - entryToken = token.toUpperCase(); + entryToken = token.toUpperCase(Locale.ENGLISH); } if (entryToken.equals("DELEGATE")) { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TextCatalogReader.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TextCatalogReader.java index 3493e48f91b..9440e3370cb 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TextCatalogReader.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/TextCatalogReader.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// TextCatalogReader.java - Read text/plain Catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -23,18 +17,19 @@ package com.sun.org.apache.xml.internal.resolver.readers; -import java.io.InputStream; -import java.io.IOException; -import java.io.FileNotFoundException; -import java.net.URL; -import java.net.URLConnection; -import java.net.MalformedURLException; -import java.util.Vector; -import java.util.Stack; import com.sun.org.apache.xml.internal.resolver.Catalog; import com.sun.org.apache.xml.internal.resolver.CatalogEntry; import com.sun.org.apache.xml.internal.resolver.CatalogException; import com.sun.org.apache.xml.internal.resolver.readers.CatalogReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URL; +import java.net.URLConnection; +import java.util.Locale; +import java.util.Stack; +import java.util.Vector; /** * Parses plain text Catalog files. @@ -140,7 +135,7 @@ public class TextCatalogReader implements CatalogReader { if (caseSensitive) { entryToken = token; } else { - entryToken = token.toUpperCase(); + entryToken = token.toUpperCase(Locale.ENGLISH); } try { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/XCatalogReader.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/XCatalogReader.java index 3d94545ae23..ce8cc40d6a8 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/XCatalogReader.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/readers/XCatalogReader.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// XCatalogReader.java - Read XML Catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -34,7 +28,7 @@ import org.xml.sax.*; import javax.xml.parsers.*; /** - * Parse "xcatalog" XML Catalog files, this is the XML Catalog format + * Parse "XCatalog" XML Catalog files, this is the XML Catalog format * developed by John Cowan and supported by Apache. * * @see Catalog @@ -52,6 +46,7 @@ public class XCatalogReader extends SAXCatalogReader implements SAXCatalogParser /** Set the current catalog. */ public void setCatalog (Catalog catalog) { this.catalog = catalog; + debug = catalog.getCatalogManager().debug; } /** Get the current catalog. */ @@ -59,13 +54,19 @@ public class XCatalogReader extends SAXCatalogReader implements SAXCatalogParser return catalog; } - /** The constructor */ - public XCatalogReader(SAXParserFactory parserFactory) { + /** Default constructor */ + public XCatalogReader() { + super(); + } + + /** Constructor allowing for providing custom SAX parser factory */ + public XCatalogReader(SAXParserFactory parserFactory, Catalog catalog) { super(parserFactory); + setCatalog(catalog); } // ---------------------------------------------------------------------- - // Implement the SAX DocumentHandler interface + // Implement the SAX ContentHandler interface /** The SAX setDocumentLocator method does nothing. */ public void setDocumentLocator (Locator locator) { @@ -106,44 +107,44 @@ public class XCatalogReader extends SAXCatalogReader implements SAXCatalogParser Vector entryArgs = new Vector(); if (localName.equals("Base")) { - entryType = catalog.BASE; + entryType = Catalog.BASE; entryArgs.add(atts.getValue("HRef")); - catalog.getCatalogManager().debug.message(4, "Base", atts.getValue("HRef")); + debug.message(4, "Base", atts.getValue("HRef")); } else if (localName.equals("Delegate")) { - entryType = catalog.DELEGATE_PUBLIC; - entryArgs.add(atts.getValue("PublicId")); + entryType = Catalog.DELEGATE_PUBLIC; + entryArgs.add(atts.getValue("PublicID")); entryArgs.add(atts.getValue("HRef")); - catalog.getCatalogManager().debug.message(4, "Delegate", - PublicId.normalize(atts.getValue("PublicId")), + debug.message(4, "Delegate", + PublicId.normalize(atts.getValue("PublicID")), atts.getValue("HRef")); } else if (localName.equals("Extend")) { - entryType = catalog.CATALOG; + entryType = Catalog.CATALOG; entryArgs.add(atts.getValue("HRef")); - catalog.getCatalogManager().debug.message(4, "Extend", atts.getValue("HRef")); + debug.message(4, "Extend", atts.getValue("HRef")); } else if (localName.equals("Map")) { - entryType = catalog.PUBLIC; - entryArgs.add(atts.getValue("PublicId")); + entryType = Catalog.PUBLIC; + entryArgs.add(atts.getValue("PublicID")); entryArgs.add(atts.getValue("HRef")); - catalog.getCatalogManager().debug.message(4, "Map", - PublicId.normalize(atts.getValue("PublicId")), + debug.message(4, "Map", + PublicId.normalize(atts.getValue("PublicID")), atts.getValue("HRef")); } else if (localName.equals("Remap")) { - entryType = catalog.SYSTEM; - entryArgs.add(atts.getValue("SystemId")); + entryType = Catalog.SYSTEM; + entryArgs.add(atts.getValue("SystemID")); entryArgs.add(atts.getValue("HRef")); - catalog.getCatalogManager().debug.message(4, "Remap", - atts.getValue("SystemId"), + debug.message(4, "Remap", + atts.getValue("SystemID"), atts.getValue("HRef")); - } else if (localName.equals("XMLCatalog")) { + } else if (localName.equals("XCatalog")) { // nop, start of catalog } else { // This is equivalent to an invalid catalog entry type - catalog.getCatalogManager().debug.message(1, "Invalid catalog entry type", localName); + debug.message(1, "Invalid catalog entry type", localName); } if (entryType >= 0) { @@ -152,21 +153,21 @@ public class XCatalogReader extends SAXCatalogReader implements SAXCatalogParser catalog.addEntry(ce); } catch (CatalogException cex) { if (cex.getExceptionType() == CatalogException.INVALID_ENTRY_TYPE) { - catalog.getCatalogManager().debug.message(1, "Invalid catalog entry type", localName); + debug.message(1, "Invalid catalog entry type", localName); } else if (cex.getExceptionType() == CatalogException.INVALID_ENTRY) { - catalog.getCatalogManager().debug.message(1, "Invalid catalog entry", localName); + debug.message(1, "Invalid catalog entry", localName); } } } - } + } - /** The SAX endElement method does nothing. */ - public void endElement (String namespaceURI, - String localName, - String qName) - throws SAXException { - return; - } + /** The SAX endElement method does nothing. */ + public void endElement (String namespaceURI, + String localName, + String qName) + throws SAXException { + return; + } /** The SAX characters method does nothing. */ public void characters (char ch[], int start, int length) @@ -185,4 +186,23 @@ public class XCatalogReader extends SAXCatalogReader implements SAXCatalogParser throws SAXException { return; } + + /** The SAX skippedEntity method does nothing. */ + public void skippedEntity (String name) + throws SAXException { + return; + } + + /** The SAX startPrefixMapping method does nothing. */ + public void startPrefixMapping(String prefix, String uri) + throws SAXException { + return; + } + + /** The SAX endPrefixMapping method does nothing. */ + public void endPrefixMapping(String prefix) + throws SAXException { + return; + } + } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java index 25951aa490b..bf82547188b 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/CatalogResolver.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// CatalogResolver.java - A SAX EntityResolver/JAXP URI Resolver - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -218,7 +212,10 @@ public class CatalogResolver implements EntityResolver, URIResolver { return iSource; } catch (Exception e) { - catalogManager.debug.message(1, "Failed to create InputSource", resolved); + catalogManager.debug.message(1, + "Failed to create InputSource (" + + e.toString() + + ")", resolved); return null; } } diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingParser.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingParser.java index 0d90d573a39..354ac1e60c0 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingParser.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingParser.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// ResolvingParser.java - An interface for reading catalog files - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -67,17 +61,12 @@ import com.sun.org.apache.xml.internal.resolver.helpers.FileURL; */ public class ResolvingParser implements Parser, DTDHandler, DocumentHandler, EntityResolver { - /** Make the parser Namespace aware? */ - public static boolean namespaceAware = true; - - /** Make the parser validating? */ - public static boolean validating = false; /** Suppress explanatory message? * * @see #parse(InputSource) */ - public static boolean suppressExplanation = false; + private static final boolean suppressExplanation = false; /** The underlying parser. */ private SAXParser saxParser = null; @@ -103,9 +92,6 @@ public class ResolvingParser /** Are we in the prolog? Is an oasis-xml-catalog PI valid now? */ private boolean allowXMLCatalogPI = false; - /** Has an oasis-xml-catalog PI been seen? */ - private boolean oasisXMLCatalogPI = false; - /** The base URI of the input document, if known. */ private URL baseURL = null; @@ -125,8 +111,8 @@ public class ResolvingParser catalogResolver = new CatalogResolver(catalogManager); SAXParserFactory spf = catalogManager.useServicesMechanism() ? SAXParserFactory.newInstance() : new SAXParserFactoryImpl(); - spf.setNamespaceAware(namespaceAware); - spf.setValidating(validating); + spf.setNamespaceAware(true); + spf.setValidating(false); try { saxParser = spf.newSAXParser(); @@ -289,7 +275,6 @@ public class ResolvingParser if (catalog != null) { try { catalogManager.debug.message(4,"oasis-xml-catalog", catalog.toString()); - oasisXMLCatalogPI = true; if (piCatalogResolver == null) { piCatalogResolver = new CatalogResolver(true); @@ -396,7 +381,10 @@ public class ResolvingParser return iSource; } catch (Exception e) { - catalogManager.debug.message(1, "Failed to create InputSource", resolved); + catalogManager.debug.message(1, + "Failed to create InputSource (" + + e.toString() + + ")", resolved); return null; } } else { diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLFilter.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLFilter.java index 660e4af6a13..f196e3726fe 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLFilter.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLFilter.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// ResolvingXMLFilter.java - An XMLFilter that performs catalog resolution - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -61,7 +55,7 @@ public class ResolvingXMLFilter extends XMLFilterImpl { * * @see #parse(InputSource) */ - public static boolean suppressExplanation = false; + private static boolean suppressExplanation = false; /** The manager for the underlying resolver. */ CatalogManager catalogManager = CatalogManager.getStaticManager(); @@ -75,9 +69,6 @@ public class ResolvingXMLFilter extends XMLFilterImpl { /** Are we in the prolog? Is an oasis-xml-catalog PI valid now? */ private boolean allowXMLCatalogPI = false; - /** Has an oasis-xml-catalog PI been seen? */ - private boolean oasisXMLCatalogPI = false; - /** The base URI of the input document, if known. */ private URL baseURL = null; @@ -202,7 +193,10 @@ public class ResolvingXMLFilter extends XMLFilterImpl { return iSource; } catch (Exception e) { - catalogManager.debug.message(1, "Failed to create InputSource", resolved); + catalogManager.debug.message(1, + "Failed to create InputSource (" + + e.toString() + + ")", resolved); return null; } } else { @@ -289,7 +283,6 @@ public class ResolvingXMLFilter extends XMLFilterImpl { if (catalog != null) { try { catalogManager.debug.message(4,"oasis-xml-catalog", catalog.toString()); - oasisXMLCatalogPI = true; if (piCatalogResolver == null) { piCatalogResolver = new CatalogResolver(true); diff --git a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLReader.java b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLReader.java index 0a98cd8dbe6..ad9bd7c6e19 100644 --- a/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLReader.java +++ b/jaxp/src/java.xml/share/classes/com/sun/org/apache/xml/internal/resolver/tools/ResolvingXMLReader.java @@ -1,16 +1,10 @@ /* - * reserved comment block - * DO NOT REMOVE OR ALTER! - */ -// ResolvingXMLReader.java - An XMLReader that performs catalog resolution - -/* - * Copyright 2001-2004 The Apache Software Foundation or its licensors, - * as applicable. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * @@ -23,7 +17,6 @@ package com.sun.org.apache.xml.internal.resolver.tools; -import org.xml.sax.*; import javax.xml.parsers.*; @@ -48,10 +41,10 @@ import com.sun.org.apache.xml.internal.resolver.*; */ public class ResolvingXMLReader extends ResolvingXMLFilter { /** Make the parser Namespace aware? */ - public static boolean namespaceAware = true; + private static final boolean namespaceAware = true; /** Make the parser validating? */ - public static boolean validating = false; + private static final boolean validating = false; /** * Construct a new reader from the JAXP factory. diff --git a/jaxws/.hgignore b/jaxws/.hgignore index 36b21b16e0c..94668d195b7 100644 --- a/jaxws/.hgignore +++ b/jaxws/.hgignore @@ -2,7 +2,7 @@ ^dist/ ^drop/ ^drop_included/ -^webrev/ +^webrev /nbproject/private/ ^.hgtip .DS_Store diff --git a/jaxws/.hgtags b/jaxws/.hgtags index 121910c3483..e768a03efa3 100644 --- a/jaxws/.hgtags +++ b/jaxws/.hgtags @@ -272,3 +272,7 @@ ce19e0403ec8a80223cc47320c905b2a4d45881d jdk9-b23 0b35542d6bf32af23a9fc59a37c52aa091fee388 jdk9-b24 ab8726a0fcde897e4cfd1ea581ed90b0d8a7cbb7 jdk9-b25 9b43f3993b96c2213428e95127a2d3fd0e709d3a jdk9-b26 +dcaa586ab756420e9a62643793bacef2c84bf637 jdk9-b27 +5282a14f131f897cc9575872c0fae72d47dc4e65 jdk9-b28 +3d1a4bfb6abbf5011ba6d8896301ee3b6ef3ba72 jdk9-b29 +e58d3ea638c3824f01547596b2a98aa5f77c4a5c jdk9-b30 diff --git a/jdk/.hgignore b/jdk/.hgignore index d8754b13e1f..1ed4344d03f 100644 --- a/jdk/.hgignore +++ b/jdk/.hgignore @@ -1,5 +1,6 @@ ^build/ ^dist/ +^webrev ^testoutput/ /nbproject/private/ ^make/netbeans/.*/build/ diff --git a/jdk/.hgtags b/jdk/.hgtags index 9b0360a42ef..bea594c1bfc 100644 --- a/jdk/.hgtags +++ b/jdk/.hgtags @@ -269,3 +269,7 @@ f87c5be90e01a7ffb47947108eb3e0b0b1920880 jdk9-b20 875450e7ef8dde8f59db662ec1351ea30b8cb35d jdk9-b24 a31efe49556a7c12f9ea2c9ee8b4fae8aa67723a jdk9-b25 dde9f5cfde5f46e62ceb5fab81151578e5277aef jdk9-b26 +f0870554049807d3392bd7976ab114f7f2b7bafa jdk9-b27 +1828f73b35cfe35e460e41fd6e087ab1f83e0621 jdk9-b28 +2da27e8e2c865e154f0c2eb9009f011a44649b11 jdk9-b29 +8d24fb4493f13d380a2adf62d444e1e5a4451f37 jdk9-b30 diff --git a/jdk/make/Bundles.gmk b/jdk/make/Bundles.gmk index 57ab08784cf..470a1e9bfb5 100644 --- a/jdk/make/Bundles.gmk +++ b/jdk/make/Bundles.gmk @@ -35,7 +35,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx) # JDK_BUNDLE_DIR and JRE_BUNDLE_DIR are defined in SPEC. - MACOSX_PLIST_SRC := $(JDK_TOPDIR)/make/bundle + MACOSX_PLIST_SRC := $(JDK_TOPDIR)/make/data/bundle # All these OPENJDK checks are needed since there is no coherency between # these values in open and closed. Should probably be fixed. diff --git a/jdk/make/CompileDemos.gmk b/jdk/make/CompileDemos.gmk index 531e61765a2..35bf0b4a691 100644 --- a/jdk/make/CompileDemos.gmk +++ b/jdk/make/CompileDemos.gmk @@ -29,9 +29,7 @@ include $(SPEC) include MakeBase.gmk include JavaCompilation.gmk include NativeCompilation.gmk - -# Setup the java compilers for the JDK build. -include SetupJava.gmk +include SetupJavaCompilers.gmk # Prepare the find cache. $(eval $(call FillCacheFind, $(JDK_TOPDIR)/src)) @@ -316,19 +314,6 @@ $(eval $(call SetupJVMTIDemo,compiledMethodLoad, agent_util)) $(eval $(call SetupJVMTIDemo,gctest, agent_util)) $(eval $(call SetupJVMTIDemo,heapTracker, agent_util java_crw_demo)) $(eval $(call SetupJVMTIDemo,heapViewer, agent_util)) - -# On AIX, hprof requires 'dladdr' from src/aix/porting/porting_aix.cpp -BUILD_LIBHPROF_AIX_EXTRA_SRC := -BUILD_LIBHPROF_AIX_EXTRA_CFLAGS := -ifeq ($(OPENJDK_TARGET_OS), aix) - BUILD_LIBHPROF_AIX_EXTRA_SRC += $(JDK_TOPDIR)/src/aix/porting - BUILD_LIBHPROF_AIX_EXTRA_CFLAGS += -I$(JDK_TOPDIR)/src/aix/porting -endif - -$(eval $(call SetupJVMTIDemo,hprof, java_crw_demo, \ - $(BUILD_LIBHPROF_AIX_EXTRA_CFLAGS), C, \ - -ldl, ws2_32.lib winmm.lib, -lsocket -lnsl, -lpthread, $(BUILD_LIBHPROF_AIX_EXTRA_SRC))) - $(eval $(call SetupJVMTIDemo,minst, agent_util java_crw_demo)) $(eval $(call SetupJVMTIDemo,mtrace, agent_util java_crw_demo)) $(eval $(call SetupJVMTIDemo,waiters, agent_util, , C++)) @@ -336,34 +321,6 @@ $(eval $(call SetupJVMTIDemo,versionCheck, agent_util)) ################################################################################################## -$(JDK_OUTPUTDIR)/demo/jpda/com/sun/tools/example/README: \ - $(JDK_TOPDIR)/src/demo/share/jpda/com/sun/tools/example/README - $(call install-file) - $(CHMOD) -f ug+w $@ - -$(eval $(call SetupArchive,JPDA_JAR, \ - $(JDK_OUTPUTDIR)/demo/jpda/com/sun/tools/example/README, \ - SRCS := $(JDK_TOPDIR)/src/demo/share/jpda \ - $(JDK_TOPDIR)/src/jdk.jdi/share/classes \ - $(JDK_OUTPUTDIR)/demo/jpda/com/sun/tools/example, \ - INCLUDES := com/sun/tools/example README, \ - SUFFIXES := .java .html .jj README, \ - JAR := $(JDK_OUTPUTDIR)/demo/jpda/examples.jar, \ - MANIFEST := $(JDK_TOPDIR)/make/data/mainmanifest/manifest.mf, \ - EXTRA_MANIFEST_ATTR := Main-Class:$$(SPACE), \ - SKIP_METAINF := true)) - -$(eval $(call SetupZipArchive,JPDA_ZIP, \ - SRC := $(JDK_TOPDIR)/src/demo/share/jpda \ - $(JDK_TOPDIR)/src/jdk.jdi/share/classes, \ - INCLUDES := com/sun/tools/example, \ - SUFFIXES := .java .html .jj README, \ - ZIP := $(JDK_OUTPUTDIR)/demo/jpda/src.zip)) - -BUILD_DEMOS += $(JPDA_JAR) $(JPDA_ZIP) - -################################################################################################## - $(JDK_OUTPUTDIR)/demo/management/index.html: $(DEMO_SHARE_SRC)/management/index.html $(call install-file) $(CHMOD) -f ug+w $@ diff --git a/jdk/make/CompileInterimRmic.gmk b/jdk/make/CompileInterimRmic.gmk index 74f789dfa61..79082cd415c 100644 --- a/jdk/make/CompileInterimRmic.gmk +++ b/jdk/make/CompileInterimRmic.gmk @@ -28,7 +28,7 @@ default: all include $(SPEC) include MakeBase.gmk include JavaCompilation.gmk -include SetupJava.gmk +include SetupJavaCompilers.gmk ########################################################################################## diff --git a/jdk/make/CopyIntoClasses.gmk b/jdk/make/CopyIntoClasses.gmk deleted file mode 100644 index a80c661ace9..00000000000 --- a/jdk/make/CopyIntoClasses.gmk +++ /dev/null @@ -1,202 +0,0 @@ -# -# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# - -# Copy icu and _dict files used by the text break iterator - -COPY_PATTERNS := .icu _dict .dat _options .js aliasmap .spp .wav .css \ - .png .gif .xml .dtd .txt oqlhelp.html content-types.properties - -# These directories should not be copied at all -EXCLUDES += \ - java/awt/doc-files \ - java/lang/doc-files \ - javax/swing/doc-files \ - javax/swing/text/doc-files \ - javax/swing/plaf/synth/doc-files \ - javax/swing/undo/doc-files \ - sun/awt/X11/doc-files \ - sun/util/cldr/resources \ - # - -# These files should never be included -EXFILES += build.xml README.txt version.txt - -# These icons are handled in GensrcIcons.gmk -EXFILES += \ - sun/awt/X11/java-icon16.png \ - sun/awt/X11/java-icon24.png \ - sun/awt/X11/java-icon32.png \ - sun/awt/X11/java-icon48.png \ - $(wildcard $(JDK_TOPDIR)/src/share/classes/sun/awt/resources/*.png) \ - # - -ifndef OPENJDK - # Theses icons have closed replacements - SWING_PLAF_MOTIF_RESOURCES_DIR := $(JDK_TOPDIR)/src/share/classes/com/sun/java/swing/plaf/motif - EXFILES += \ - $(JDK_TOPDIR)/src/share/classes/com/sun/java/swing/plaf/windows/icons/JavaCup32.png \ - $(JDK_TOPDIR)/src/share/classes/javax/swing/plaf/basic/icons/JavaCup16.png \ - $(wildcard $(SWING_PLAF_MOTIF_RESOURCES_DIR)/icons/*.gif) \ - $(wildcard $(SWING_PLAF_MOTIF_RESOURCES_DIR)/icons/*.png) \ - # - - EXFILES += mib_core.txt -endif - -ifeq ($(ENABLE_JFR), true) - JFR_CONFIGURATION_DIR_CLOSED := $(JDK_TOPDIR)/src/closed/share/classes/oracle/jrockit/jfr/settings - COPY_FILES += \ - $(JFR_CONFIGURATION_DIR_CLOSED)/jfc.xsd -endif - -SWING_BEANINFO_RESOURCES_SRC_DIR = $(JDK_TOPDIR)/make/data/swingbeaninfo/images -SWING_BEANINFO_RESOURCES_SRC = $(wildcard $(SWING_BEANINFO_RESOURCES_SRC_DIR)/*.gif) -OUT_BEANINFO_RESOURCES = $(patsubst $(SWING_BEANINFO_RESOURCES_SRC_DIR)%, \ - $(JDK_OUTPUTDIR)/classes/javax/swing/beaninfo/images/%, \ - $(SWING_BEANINFO_RESOURCES_SRC)) - -COPY_EXTRA += $(OUT_BEANINFO_RESOURCES) - -# The exception handling of swing beaninfo -# These resources violates the convention of having code and resources together under -# $(JDK_TOPDIR)/src/.../classes directories -$(JDK_OUTPUTDIR)/classes/javax/swing/beaninfo/images/%.gif: \ - $(JDK_TOPDIR)/make/data/swingbeaninfo/images/%.gif - $(call install-file) - -########################################################################################## -# -# Copy the META-INF/services configuration files that are scattered around the source tree -# into classes/META-INF/services. Be aware that META-INF directories that are located at a -# source root (.../classes/META-INF) are automatically copied verbatim by the -# SetupJavaCompilation macro. -# -# Any other META-INF/services configuration file is found here and platform specific comments -# are uncommented and the configuration file is stored in the output META-INF directory. - -# Make sure the output directory is created. -$(eval $(call MakeDir, $(JDK_OUTPUTDIR)/classes/META-INF/services)) -# Find all META-INF/services/* files -ALL_META-INF_DIRS_share := $(shell $(FIND) $(JDK_TOPDIR)/src/share/classes -type d -a -name META-INF) -ALL_META-INF_DIRS_targetapi := $(shell $(FIND) $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes -type d -a -name META-INF) -# Platform specific overrides shared -ifneq ($(ALL_META-INF_DIRS_targetapi), ) - ALL_META-INF_DIRS := $(ALL_META-INF_DIRS_targetapi) \ - $(filter-out %$(patsubst $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes%,%,$(ALL_META-INF_DIRS_targetapi)), \ - $(ALL_META-INF_DIRS_share)) -else - ALL_META-INF_DIRS := $(ALL_META-INF_DIRS_share) -endif - -SRC_SERVICES_FILES := $(wildcard $(addsuffix /services/*, $(ALL_META-INF_DIRS))) - -# The number of services files are relatively few. If the increase in numbers, then -# we have to use ListPathsSafelyNow here. -# Change $(JDK_TOPDIR)/src/.../META-INF/services/yyyy into $(JDK_OUTPUTDIR)/classes/META-INF/services/yyyy -# The \n in the printf command is needed to make sed work on Solaris. -OUT_SERVICES_FILES := $(addprefix $(JDK_OUTPUTDIR)/classes/META-INF/services/, \ - $(shell $(PRINTF) "$(SRC_SERVICES_FILES)\n" | $(SED) -e 's|/[^ ]*/META-INF/services/||g')) -OUT_SERVICES_FILES_COLON := $(addsuffix :, $(OUT_SERVICES_FILES)) -# Exception handling for print services with no META-INF directory -SRC_SERVICES_FILES_PRINT = $(wildcard $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes/sun/print/services/*) -OUT_SERVICES_FILES_PRINT = $(addprefix $(JDK_OUTPUTDIR)/classes/META-INF/services/, \ - $(patsubst $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes/sun/print/services/%, %, \ - $(SRC_SERVICES_FILES_PRINT))) -OUT_SERVICES_FILES_PRINT_COLON = $(addsuffix :, $(OUT_SERVICES_FILES_PRINT)) -RULES_SERVICES_PRINT = $(join $(OUT_SERVICES_FILES_PRINT_COLON), $(SRC_SERVICES_FILES_PRINT)) - -# Now setup the dependency rules to generate a META-INF/services/... from the correct source. -META-INF_RULES_SERVICES := $(RULES_SERVICES_PRINT) $(join $(OUT_SERVICES_FILES_COLON), $(SRC_SERVICES_FILES)) -# Eval the newly created rules to incorporate them into the make tree. -define addto_meta-inf_services - $1 - echo $(LOG_INFO) Installing META-INF/services/$$(@F) - $(CAT) $$< | $(SED) -e "s/^#\[$(OPENJDK_TARGET_OS)\]//" > $$@ -endef -$(foreach i, $(META-INF_RULES_SERVICES), $(eval $(call addto_meta-inf_services, $i))) -# Here is the generic rule, whose receipt the above rules will trigger. - -COPY_EXTRA += $(OUT_SERVICES_FILES) -COPY_EXTRA += $(OUT_SERVICES_FILES_PRINT) - -################################################################################ - -JAVAX_SOUND_SRC := $(JDK_TOPDIR)/src/share/classes/com/sun/media/sound/services - -JAVAX_SOUND_SRC_FILES := \ - javax.sound.midi.spi.MidiDeviceProvider \ - javax.sound.midi.spi.MidiFileReader \ - javax.sound.midi.spi.MidiFileWriter \ - javax.sound.midi.spi.SoundbankReader \ - javax.sound.sampled.spi.AudioFileReader \ - javax.sound.sampled.spi.AudioFileWriter \ - javax.sound.sampled.spi.FormatConversionProvider \ - javax.sound.sampled.spi.MixerProvider - -COPY_EXTRA += $(addprefix $(JDK_OUTPUTDIR)/classes/META-INF/services/, $(JAVAX_SOUND_SRC_FILES)) - -JAVAX_SOUND_RULES := $(foreach F, $(JAVAX_SOUND_SRC_FILES), $(JDK_OUTPUTDIR)/classes/META-INF/services/$(notdir $F):$(JAVAX_SOUND_SRC)/$F) - -$(foreach R, $(JAVAX_SOUND_RULES), $(eval $(call addto_meta-inf_services, $R))) - -################################################################################ - -ifneq ($(OPENJDK_TARGET_OS), macosx) - OPENJDK_TARGET_OS_FLAVORMAP_PROPERTIES = $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes/sun/awt/datatransfer/flavormap.properties -else - OPENJDK_TARGET_OS_FLAVORMAP_PROPERTIES = $(JDK_TOPDIR)/src/macosx/classes/sun/awt/datatransfer/flavormap.properties -endif - -$(JDK_OUTPUTDIR)/classes/sun/awt/datatransfer/flavormap.properties: $(OPENJDK_TARGET_OS_FLAVORMAP_PROPERTIES) - $(install-file) - -COPY_EXTRA += $(JDK_OUTPUTDIR)/classes/sun/awt/datatransfer/flavormap.properties - -################################################################################ - -CLEAN_FILES := $(wildcard \ - $(JDK_TOPDIR)/src/share/classes/com/sun/imageio/plugins/common/*.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/java/util/jar/pack/*.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/jndi/cosnaming/jndiprovider.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/jndi/ldap/jndiprovider.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/org/apache/xml/internal/security/resource/*.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/rowset/*.properties \ - $(JDK_TOPDIR)/src/share/classes/com/sun/tools/script/shell/*.properties \ - $(JDK_TOPDIR)/src/share/classes/javax/sql/rowset/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/rmi/registry/resources/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/rmi/rmic/resources/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/rmi/server/resources/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/tools/javac/resources/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/tools/jconsole/resources/*.properties \ - $(JDK_TOPDIR)/src/share/classes/sun/tools/serialver/resources/*.properties \ - ) - -# Copy zh_HK files from zh_TW - -$(JDK_OUTPUTDIR)/classes/%_zh_HK.properties: $(JDK_OUTPUTDIR)/classes/%_zh_TW.properties - $(install-file) - -COPY_EXTRA += $(patsubst $(JDK_TOPDIR)/src/share/classes/%, $(JDK_OUTPUTDIR)/classes/%, \ - $(subst _zh_TW,_zh_HK, $(filter %_zh_TW.properties, $(CLEAN_FILES)))) diff --git a/jdk/make/CreateJars.gmk b/jdk/make/CreateJars.gmk index 1e250456507..aca0f42904a 100644 --- a/jdk/make/CreateJars.gmk +++ b/jdk/make/CreateJars.gmk @@ -76,13 +76,24 @@ LOCALEDATA_INCLUDE_LOCALES := ar be bg ca cs da de el es et fi fr ga hi hr hu in iw ja ko lt lv mk ms mt nl no pl pt ro ru sk sl sq sr sv \ th tr uk vi zh -LOCALEDATA_INCLUDES := $(addprefix sun/text/resources/, $(LOCALEDATA_INCLUDE_LOCALES)) \ +LOCALEDATA_INCLUDES := sun/util/resources/provider/NonEnLocaleDataMetaInfo.class +LOCALEDATA_INCLUDES += $(addprefix sun/text/resources/, $(LOCALEDATA_INCLUDE_LOCALES)) \ $(addprefix sun/util/resources/, $(LOCALEDATA_INCLUDE_LOCALES)) -$(eval $(call SetupArchive,BUILD_LOCALEDATA_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata, \ +LOCALEDATA_SERVICES_DIR := $(IMAGES_OUTPUTDIR)/localemetainfo + +LOCALEDATA_METAINF_SERVICES := $(LOCALEDATA_SERVICES_DIR)/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo + +$(LOCALEDATA_METAINF_SERVICES): $(JDK_TOPDIR)/src/jdk.localedata/META-INF/localedata-services/sun.util.locale.provider.LocaleDataMetaInfo + $(install-file) + +$(eval $(call SetupArchive,BUILD_LOCALEDATA_JAR, \ + $(LOCALEDATA_METAINF_SERVICES), \ + SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata \ + $(LOCALEDATA_SERVICES_DIR), \ SUFFIXES := .class _dict _th, \ INCLUDES := $(LOCALEDATA_INCLUDES), \ + EXTRA_FILES := META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo, \ JAR := $(IMAGES_OUTPUTDIR)/lib/ext/localedata.jar, \ SKIP_METAINF := true)) @@ -210,6 +221,8 @@ RT_JAR_EXCLUDES += \ sun/tools/tree \ sun/tools/util \ sun/util/cldr/CLDRLocaleDataMetaInfo.class \ + sun/util/resources/provider/NonEnLocaleDataMetaInfo.class \ + META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo \ sun/util/resources/cldr \ $(LOCALEDATA_INCLUDES) \ com/oracle/jrockit/jfr \ @@ -429,13 +442,23 @@ include gensrc/GensrcCLDR.gmk CLDRDATA_JAR_DST := $(IMAGES_OUTPUTDIR)/lib/ext/cldrdata.jar -$(eval $(call SetupArchive,BUILD_CLDRDATA_JAR, , \ +CLDR_SERVICES_DIR := $(IMAGES_OUTPUTDIR)/cldrmetainfo + +CLDR_METAINF_SERVICES := $(CLDR_SERVICES_DIR)/META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo + +$(CLDR_METAINF_SERVICES): $(JDK_TOPDIR)/src/jdk.localedata/META-INF/cldrdata-services/sun.util.locale.provider.LocaleDataMetaInfo + $(install-file) + +$(eval $(call SetupArchive,BUILD_CLDRDATA_JAR, \ + $(CLDR_METAINF_SERVICES), \ SRCS := $(JDK_OUTPUTDIR)/modules/jdk.localedata \ - $(JDK_OUTPUTDIR)/modules/java.base, \ + $(JDK_OUTPUTDIR)/modules/java.base \ + $(CLDR_SERVICES_DIR), \ SUFFIXES := .class, \ INCLUDES := sun/text/resources/cldr \ sun/util/cldr/CLDRLocaleDataMetaInfo.class \ sun/util/resources/cldr, \ + EXTRA_FILES := META-INF/services/sun.util.locale.provider.LocaleDataMetaInfo, \ JAR := $(CLDRDATA_JAR_DST), \ EXTRA_MANIFEST_ATTR := CLDR-Version: $(CLDRVERSION), \ SKIP_METAINF := true)) @@ -524,7 +547,6 @@ $(eval $(call SetupArchive,BUILD_TOOLS_JAR, , \ EXCLUDES := $(TOOLS_JAR_EXCLUDES), \ EXTRA_FILES := \ $(JDK_OUTPUTDIR)/modules/jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector \ - $(JDK_OUTPUTDIR)/classes/META-INF/services/com.sun.jdi.connect.Connector \ META-INF/services/com.sun.jdi.connect.spi.TransportService \ META-INF/services/com.sun.tools.attach.spi.AttachProvider \ META-INF/services/com.sun.tools.internal.ws.wscompile.Plugin \ diff --git a/jdk/make/CreateSecurityJars.gmk b/jdk/make/CreateSecurityJars.gmk index 1a3d3343c53..097ac813821 100644 --- a/jdk/make/CreateSecurityJars.gmk +++ b/jdk/make/CreateSecurityJars.gmk @@ -32,8 +32,6 @@ include JavaCompilation.gmk # The jars created in this file are required for the exploded jdk image to function and # cannot wait to be built in the images target. -SECURITY_CLASSES_SUBDIR := modules - ########################################################################################## # Create manifest for security jars # @@ -67,7 +65,7 @@ SUNPKCS11_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/sunpkcs11.jar SUNPKCS11_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/sunpkcs11.jar $(eval $(call SetupArchive,BUILD_SUNPKCS11_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/jdk.crypto.pkcs11, \ + SRCS := $(JDK_OUTPUTDIR)/modules/jdk.crypto.pkcs11, \ SUFFIXES := .class, \ INCLUDES := sun/security/pkcs11, \ JAR := $(SUNPKCS11_JAR_UNSIGNED), \ @@ -94,7 +92,7 @@ SUNEC_JAR_DST := $(JDK_OUTPUTDIR)/lib/ext/sunec.jar SUNEC_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/sunec.jar $(eval $(call SetupArchive,BUILD_SUNEC_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/jdk.crypto.ec, \ + SRCS := $(JDK_OUTPUTDIR)/modules/jdk.crypto.ec, \ SUFFIXES := .class, \ INCLUDES := sun/security/ec, \ JAR := $(SUNEC_JAR_UNSIGNED), \ @@ -122,7 +120,7 @@ SUNJCE_PROVIDER_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/sunjce_provider.ja ifneq ($(BUILD_CRYPTO), no) $(eval $(call SetupArchive,BUILD_SUNJCE_PROVIDER_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/java.base, \ + SRCS := $(JDK_OUTPUTDIR)/modules/java.base, \ SUFFIXES := .class, \ INCLUDES := com/sun/crypto/provider, \ JAR := $(SUNJCE_PROVIDER_JAR_UNSIGNED), \ @@ -153,7 +151,7 @@ JCE_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/jce.jar ifneq ($(BUILD_CRYPTO), no) $(eval $(call SetupArchive,BUILD_JCE_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/java.base, \ + SRCS := $(JDK_OUTPUTDIR)/modules/java.base, \ SUFFIXES := .class, \ INCLUDES := javax/crypto sun/security/internal, \ JAR := $(JCE_JAR_UNSIGNED), \ @@ -185,7 +183,7 @@ ifeq ($(OPENJDK_TARGET_OS), windows) SUNMSCAPI_JAR_UNSIGNED := $(JDK_OUTPUTDIR)/jce/unsigned/sunmscapi.jar $(eval $(call SetupArchive,BUILD_SUNMSCAPI_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/jdk.crypto.mscapi, \ + SRCS := $(JDK_OUTPUTDIR)/modules/jdk.crypto.mscapi, \ SUFFIXES := .class, \ INCLUDES := sun/security/mscapi, \ JAR := $(SUNMSCAPI_JAR_UNSIGNED), \ @@ -218,7 +216,7 @@ ifeq ($(OPENJDK_TARGET_OS), solaris) UCRYPTO_JAR_SRC := $(JDK_TOPDIR)/make/closed/tools/crypto/ucrypto/ucrypto.jar $(eval $(call SetupArchive,BUILD_UCRYPTO_JAR, , \ - SRCS := $(JDK_OUTPUTDIR)/$(SECURITY_CLASSES_SUBDIR)/jdk.crypto.ucrypto, \ + SRCS := $(JDK_OUTPUTDIR)/modules/jdk.crypto.ucrypto, \ SUFFIXES := .class, \ INCLUDES := com/oracle/security/ucrypto, \ JAR := $(UCRYPTO_JAR_UNSIGNED), \ diff --git a/jdk/make/Tools.gmk b/jdk/make/Tools.gmk index c384643ab67..b68d19c3d34 100644 --- a/jdk/make/Tools.gmk +++ b/jdk/make/Tools.gmk @@ -32,10 +32,7 @@ include $(SPEC) include MakeBase.gmk include JavaCompilation.gmk include NativeCompilation.gmk -include SetupJava.gmk - -# Cache all finds needed for this file. -$(eval $(call FillCacheFind, $(JDK_TOPDIR)/make/src/classes)) +include SetupJavaCompilers.gmk # The exception handling of swing beaninfo which have the own tool directory ifeq (, $(BUILD_TOOLS_JDK)) @@ -101,6 +98,9 @@ TOOL_TZDB = $(JAVA_SMALL) -cp $(JDK_OUTPUTDIR)/btclasses \ TOOL_BLACKLISTED_CERTS = $(JAVA_SMALL) -cp $(JDK_OUTPUTDIR)/btclasses \ build.tools.blacklistedcertsconverter.BlacklistedCertsConverter +TOOL_MAKEJAVASECURITY = $(JAVA_SMALL) -cp $(JDK_OUTPUTDIR)/btclasses \ + build.tools.makejavasecurity.MakeJavaSecurity + # TODO: There are references to the jdwpgen.jar in jdk/make/netbeans/jdwpgen/build.xml # and nbproject/project.properties in the same dir. Needs to be looked at. @@ -134,10 +134,7 @@ TOOL_CHECKDEPS = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \ TOOL_GENMODULESXML = $(JAVA_SMALL) -Xbootclasspath/p:$(INTERIM_LANGTOOLS_JAR) \ -cp "$(JDK_OUTPUTDIR)/btclasses$(PATH_SEP)$(JDK_OUTPUTDIR)" \ - build.tools.module.GenerateModulesXml - -TOOL_ADDTORESTRICTEDPKGS = $(JAVA_SMALL) -cp $(JDK_OUTPUTDIR)/btclasses \ - build.tools.addtorestrictedpkgs.AddToRestrictedPkgs + build.tools.module.GenJdepsModulesXml ########################################################################################## diff --git a/jdk/make/copy/Copy-java.base.gmk b/jdk/make/copy/Copy-java.base.gmk index 36a2c9da66a..97fc8193ef7 100644 --- a/jdk/make/copy/Copy-java.base.gmk +++ b/jdk/make/copy/Copy-java.base.gmk @@ -32,17 +32,17 @@ $(eval $(call IncludeCustomExtension, jdk, copy/Copy-java.base.gmk)) # Copy exported header files to outputdir. # JAVA_BASE_HEADERS := \ - $(INCLUDEDIR)/jni.h \ - $(INCLUDEDIR)/jvmti.h \ - $(INCLUDEDIR)/jvmticmlr.h \ - $(INCLUDEDIR)/classfile_constants.h \ - $(OPENJDK_TARGET_OS_INCLUDE)/jni_md.h \ + $(INCLUDE_DST_DIR)/jni.h \ + $(INCLUDE_DST_DIR)/jvmti.h \ + $(INCLUDE_DST_DIR)/jvmticmlr.h \ + $(INCLUDE_DST_DIR)/classfile_constants.h \ + $(INCLUDE_DST_OS_DIR)/jni_md.h \ # -$(INCLUDEDIR)/%.h: $(JDK_TOPDIR)/src/java.base/share/native/include/%.h +$(INCLUDE_DST_DIR)/%.h: $(JDK_TOPDIR)/src/java.base/share/native/include/%.h $(call install-file) -$(OPENJDK_TARGET_OS_INCLUDE)/%.h: \ +$(INCLUDE_DST_OS_DIR)/%.h: \ $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_EXPORT_DIR)/native/include/%.h $(call install-file) @@ -50,17 +50,17 @@ $(OPENJDK_TARGET_OS_INCLUDE)/%.h: \ CALENDARS_SRC := $(JDK_TOPDIR)/src/java.base/share/conf -$(LIBDIR)/calendars.properties: $(CALENDARS_SRC)/calendars.properties +$(LIB_DST_DIR)/calendars.properties: $(CALENDARS_SRC)/calendars.properties $(call install-file) -BASE_CONF_FILES += $(LIBDIR)/calendars.properties +BASE_CONF_FILES += $(LIB_DST_DIR)/calendars.properties -$(LIBDIR)/hijrah-config-umalqura.properties: $(CALENDARS_SRC)/hijrah-config-umalqura.properties +$(LIB_DST_DIR)/hijrah-config-umalqura.properties: $(CALENDARS_SRC)/hijrah-config-umalqura.properties $(MKDIR) -p $(@D) $(RM) $@ $(CP) $< $@ -BASE_CONF_FILES += $(LIBDIR)/hijrah-config-umalqura.properties +BASE_CONF_FILES += $(LIB_DST_DIR)/hijrah-config-umalqura.properties ################################################################################ @@ -68,10 +68,10 @@ ifneq ($(findstring $(OPENJDK_TARGET_OS), windows aix),) TZMAPPINGS_SRC := $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/conf - $(LIBDIR)/tzmappings: $(TZMAPPINGS_SRC)/tzmappings + $(LIB_DST_DIR)/tzmappings: $(TZMAPPINGS_SRC)/tzmappings $(call install-file) - BASE_CONF_FILES += $(LIBDIR)/tzmappings + BASE_CONF_FILES += $(LIB_DST_DIR)/tzmappings endif @@ -208,20 +208,6 @@ BASE_CONF_FILES += $(CACERTS_DST) ################################################################################ -ifeq ($(OPENJDK_TARGET_OS), solaris) - - SUNPKCS11_CFG_SRC := $(JDK_TOPDIR)/src/java.base/share/conf/security/sunpkcs11-solaris.cfg - SUNPKCS11_CFG_DST := $(JDK_OUTPUTDIR)/lib/security/sunpkcs11-solaris.cfg - - $(SUNPKCS11_CFG_DST): $(SUNPKCS11_CFG_SRC) - $(call install-file) - - BASE_CONF_FILES += $(SUNPKCS11_CFG_DST) - -endif - -################################################################################ - $(JDK_OUTPUTDIR)/lib/net.properties: $(JDK_TOPDIR)/src/java.base/share/conf/net.properties $(ECHO) $(LOG_INFO) Copying $(@F) $(call install-file) diff --git a/jdk/make/copy/Copy-java.desktop.gmk b/jdk/make/copy/Copy-java.desktop.gmk index e724a862b28..d83f4ee926f 100644 --- a/jdk/make/copy/Copy-java.desktop.gmk +++ b/jdk/make/copy/Copy-java.desktop.gmk @@ -30,38 +30,19 @@ $(eval $(call IncludeCustomExtension, jdk, copy/Copy-java.desktop.gmk)) ################################################################################ JAVA_DESKTOP_HEADERS := \ - $(INCLUDEDIR)/jawt.h \ - $(OPENJDK_TARGET_OS_INCLUDE)/jawt_md.h \ + $(INCLUDE_DST_DIR)/jawt.h \ + $(INCLUDE_DST_OS_DIR)/jawt_md.h \ # -$(INCLUDEDIR)/%.h: $(JDK_TOPDIR)/src/java.desktop/share/native/include/%.h +$(INCLUDE_DST_DIR)/%.h: $(JDK_TOPDIR)/src/java.desktop/share/native/include/%.h $(call install-file) -$(OPENJDK_TARGET_OS_INCLUDE)/%.h: \ +$(INCLUDE_DST_OS_DIR)/%.h: \ $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_EXPORT_DIR)/native/include/%.h $(call install-file) ################################################################################ -ICCPROFILE_DEST_DIR := $(LIBDIR)/cmm - -ifdef OPENJDK - ICCPROFILE_SRC_DIR := $(JDK_TOPDIR)/src/java.desktop/share/conf/cmm/lcms -else - ICCPROFILE_SRC_DIR := $(JDK_TOPDIR)/src/closed/java.desktop/share/conf/cmm/kcms -endif - -ICCPROFILE_SRCS := $(wildcard $(ICCPROFILE_SRC_DIR)/*.pf) -ICCPROFILE_TARGET_FILES := $(subst $(ICCPROFILE_SRC_DIR),$(ICCPROFILE_DEST_DIR),$(ICCPROFILE_SRCS)) - -$(ICCPROFILE_DEST_DIR)%.pf: $(ICCPROFILE_SRC_DIR)%.pf - $(call install-file) - $(CHMOD) 444 $@ - -DESKTOP_CONF_FILES += $(ICCPROFILE_TARGET_FILES) - -################################################################################ - ifneq ($(FREETYPE_BUNDLE_LIB_PATH), ) # We need to bundle the freetype library, so it will be available at runtime as well as link time. # @@ -102,20 +83,20 @@ DESKTOP_CONF_FILES += $(JDK_OUTPUTDIR)/lib/sound.properties ################################################################################ # -# Copy property files from sun/print to LIBDIR +# Copy property files from sun/print to LIB_DST_DIR # PSFONTPROPFILE_SRC_DIR := $(JDK_TOPDIR)/src/java.desktop/share/conf PSFONTPROPFILE_SRCS := $(wildcard $(PSFONTPROPFILE_SRC_DIR)/psfont*.properties*) -PSFONTPROPFILE_TARGET_FILES := $(subst $(PSFONTPROPFILE_SRC_DIR),$(LIBDIR),$(PSFONTPROPFILE_SRCS)) +PSFONTPROPFILE_TARGET_FILES := $(subst $(PSFONTPROPFILE_SRC_DIR),$(LIB_DST_DIR),$(PSFONTPROPFILE_SRCS)) -$(LIBDIR)/%: $(PSFONTPROPFILE_SRC_DIR)/% +$(LIB_DST_DIR)/%: $(PSFONTPROPFILE_SRC_DIR)/% $(call install-file) DESKTOP_CONF_FILES += $(PSFONTPROPFILE_TARGET_FILES) ################################################################################ # -# Copy cursor.properties and cursors gif files to LIBDIR +# Copy cursor.properties and cursors gif files to LIB_DST_DIR # ifneq ($(OPENJDK_TARGET_OS), macosx) OPENJDK_TARGET_OS_LIB_SRC := $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/conf @@ -123,7 +104,7 @@ else OPENJDK_TARGET_OS_LIB_SRC := $(JDK_TOPDIR)/src/java.desktop/macosx/conf endif -CURSORS_DEST_DIR := $(LIBDIR)/images/cursors +CURSORS_DEST_DIR := $(LIB_DST_DIR)/images/cursors CURSORS_OPENJDK_TARGET_OS_LIB_SRC := $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/conf/images/cursors $(CURSORS_DEST_DIR)/cursors.properties: $(CURSORS_OPENJDK_TARGET_OS_LIB_SRC)/cursors.properties diff --git a/jdk/make/copy/Copy-java.logging.gmk b/jdk/make/copy/Copy-java.logging.gmk index f2644df1a17..da77f247276 100644 --- a/jdk/make/copy/Copy-java.logging.gmk +++ b/jdk/make/copy/Copy-java.logging.gmk @@ -29,10 +29,10 @@ include CopyCommon.gmk LOGGING_LIB_SRC := $(JDK_TOPDIR)/src/java.logging/share/conf -$(LIBDIR)/logging.properties: $(LOGGING_LIB_SRC)/logging.properties +$(LIB_DST_DIR)/logging.properties: $(LOGGING_LIB_SRC)/logging.properties $(call install-file) -LOGGING_CONF_FILES := $(LIBDIR)/logging.properties +LOGGING_CONF_FILES := $(LIB_DST_DIR)/logging.properties ################################################################################ diff --git a/jdk/make/copy/Copy-java.management.gmk b/jdk/make/copy/Copy-java.management.gmk index 55657a963ba..2352c909cad 100644 --- a/jdk/make/copy/Copy-java.management.gmk +++ b/jdk/make/copy/Copy-java.management.gmk @@ -27,7 +27,7 @@ include CopyCommon.gmk ################################################################################ -MGMT_LIBDIR := $(LIBDIR)/management +MGMT_LIBDIR := $(LIB_DST_DIR)/management MGMT_LIB_SRC := $(JDK_TOPDIR)/src/java.management/share/conf MGMT_SRC_FILES := $(wildcard $(MGMT_LIB_SRC)/*) MGMT_TARGET_FILES := $(subst $(MGMT_LIB_SRC),$(MGMT_LIBDIR),$(MGMT_SRC_FILES)) diff --git a/jdk/test/sun/tools/jps/jps-m_2.sh b/jdk/make/copy/Copy-jdk.crypto.pkcs11.gmk similarity index 50% rename from jdk/test/sun/tools/jps/jps-m_2.sh rename to jdk/make/copy/Copy-jdk.crypto.pkcs11.gmk index b881c355244..6db3dc97a8e 100644 --- a/jdk/test/sun/tools/jps/jps-m_2.sh +++ b/jdk/make/copy/Copy-jdk.crypto.pkcs11.gmk @@ -1,10 +1,12 @@ # -# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. +# 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. +# 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 @@ -21,38 +23,28 @@ # questions. # -# @test -# @bug 5009652 -# @library ../../jvmstat/testlibrary -# @build Sleeper -# @run shell jps-m_2.sh -# @summary Test that output of 'jps -m' shows proper output for main with no args. +include CopyCommon.gmk -. ${TESTSRC-.}/../../jvmstat/testlibrary/utils.sh +################################################################################ -setup -verify_os +ifeq ($(OPENJDK_TARGET_OS), solaris) -cleanup() { - kill_proc ${SLEEPER_PID} -} + SUNPKCS11_CFG_SRC := \ + $(JDK_TOPDIR)/src/jdk.crypto.pkcs11/solaris/conf/security/sunpkcs11-solaris.cfg + SUNPKCS11_CFG_DST := $(JDK_OUTPUTDIR)/lib/security/sunpkcs11-solaris.cfg -trap 'cleanup' 0 HUP INT QUIT TERM + $(SUNPKCS11_CFG_DST): $(SUNPKCS11_CFG_SRC) + $(call install-file) -JPS="${TESTJAVA}/bin/jps" -JAVA="${TESTJAVA}/bin/java" + SECURITY_PKCS11_CONF_FILES += $(SUNPKCS11_CFG_DST) -# fire up a Sleeper that blocks indefinitely - but don't pass -# any args to Sleeper.main(), as we need to inspect jps output -# for the no args condition. -# -${JAVA} -XX:+UsePerfData -cp ${TESTCLASSPATH:-${TESTCLASSES}} Sleeper & -SLEEPER_PID=$! +endif -${JPS} -J-XX:+UsePerfData -m | awk -f ${TESTSRC}/jps-m_Output2.awk -RC=$? +################################################################################ -cleanup +jdk.crypto.pkcs11: $(SECURITY_PKCS11_CONF_FILES) -exit ${RC} +all: jdk.crypto.pkcs11 + +.PHONY: all jdk.crypto.pkcs11 diff --git a/jdk/make/copy/Copy-jdk.hprof.agent.gmk b/jdk/make/copy/Copy-jdk.hprof.agent.gmk index ccec153a5b7..069e915514f 100644 --- a/jdk/make/copy/Copy-jdk.hprof.agent.gmk +++ b/jdk/make/copy/Copy-jdk.hprof.agent.gmk @@ -27,12 +27,12 @@ include CopyCommon.gmk ################################################################################ -HPROF_SRC := $(JDK_TOPDIR)/src/demo/share/jvmti/hprof/jvm.hprof.txt +HPROF_SRC := $(JDK_TOPDIR)/src/jdk.hprof.agent/share/native/libhprof/jvm.hprof.txt -$(LIBDIR)/jvm.hprof.txt: $(HPROF_SRC) +$(LIB_DST_DIR)/jvm.hprof.txt: $(HPROF_SRC) $(call install-file) -HPROF_CONF_FILES := $(LIBDIR)/jvm.hprof.txt +HPROF_CONF_FILES := $(LIB_DST_DIR)/jvm.hprof.txt ################################################################################ diff --git a/jdk/make/copy/Copy-jdk.jdwp.agent.gmk b/jdk/make/copy/Copy-jdk.jdwp.agent.gmk index c02ae7bd9be..dd7ccf01c44 100644 --- a/jdk/make/copy/Copy-jdk.jdwp.agent.gmk +++ b/jdk/make/copy/Copy-jdk.jdwp.agent.gmk @@ -28,9 +28,9 @@ include CopyCommon.gmk ################################################################################ -JDK_DEBUG_AGENT_HEADERS := $(INCLUDEDIR)/jdwpTransport.h +JDK_DEBUG_AGENT_HEADERS := $(INCLUDE_DST_DIR)/jdwpTransport.h -$(INCLUDEDIR)/%.h: $(JDK_TOPDIR)/src/jdk.jdwp.agent/share/native/include/%.h +$(INCLUDE_DST_DIR)/%.h: $(JDK_TOPDIR)/src/jdk.jdwp.agent/share/native/include/%.h $(call install-file) ################################################################################ diff --git a/jdk/make/copy/CopyCommon.gmk b/jdk/make/copy/CopyCommon.gmk index 3baefab75c8..f9c951287fc 100644 --- a/jdk/make/copy/CopyCommon.gmk +++ b/jdk/make/copy/CopyCommon.gmk @@ -28,13 +28,13 @@ default: all include $(SPEC) include MakeBase.gmk -INCLUDEDIR = $(JDK_OUTPUTDIR)/include -LIBDIR := $(JDK_OUTPUTDIR)/lib +INCLUDE_DST_DIR := $(JDK_OUTPUTDIR)/include +LIB_DST_DIR := $(JDK_OUTPUTDIR)/lib -OPENJDK_TARGET_OS_INCLUDE = $(INCLUDEDIR)/$(OPENJDK_TARGET_OS) +INCLUDE_DST_OS_DIR := $(INCLUDE_DST_DIR)/$(OPENJDK_TARGET_OS) ifeq ($(OPENJDK_TARGET_OS), windows) - OPENJDK_TARGET_OS_INCLUDE = $(INCLUDEDIR)/win32 + INCLUDE_DST_OS_DIR := $(INCLUDE_DST_DIR)/win32 else ifeq ($(OPENJDK_TARGET_OS), macosx) - OPENJDK_TARGET_OS_INCLUDE = $(INCLUDEDIR)/darwin + INCLUDE_DST_OS_DIR := $(INCLUDE_DST_DIR)/darwin endif diff --git a/jdk/make/bundle/JDK-Info.plist b/jdk/make/data/bundle/JDK-Info.plist similarity index 100% rename from jdk/make/bundle/JDK-Info.plist rename to jdk/make/data/bundle/JDK-Info.plist diff --git a/jdk/make/bundle/JRE-Info.plist b/jdk/make/data/bundle/JRE-Info.plist similarity index 100% rename from jdk/make/bundle/JRE-Info.plist rename to jdk/make/data/bundle/JRE-Info.plist diff --git a/jdk/make/data/currency/CurrencyData.properties b/jdk/make/data/currency/CurrencyData.properties index a22ddd4b3b6..2b5a5704959 100644 --- a/jdk/make/data/currency/CurrencyData.properties +++ b/jdk/make/data/currency/CurrencyData.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2000, 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 @@ -28,7 +28,7 @@ formatVersion=1 # Version of the currency code information in this class. # It is a serial number that accompanies with each amendment. -dataVersion=156 +dataVersion=159 # List of all valid ISO 4217 currency codes. # To ensure compatibility, do not remove codes. @@ -332,7 +332,7 @@ LY=LYD # LIECHTENSTEIN LI=CHF # LITHUANIA -LT=LTL +LT=LTL;2014-12-31-22-00-00;EUR # LUXEMBOURG LU=EUR # MACAU diff --git a/jdk/make/data/fontconfig/aix.fontconfig.properties b/jdk/make/data/fontconfig/aix.fontconfig.properties index 29e7c7d9510..f203f759894 100644 --- a/jdk/make/data/fontconfig/aix.fontconfig.properties +++ b/jdk/make/data/fontconfig/aix.fontconfig.properties @@ -24,9 +24,14 @@ # questions. # -# Minimal version for AIX using the standard Latin Type1 Fonts from the -# package X11.fnt.iso_T1. These fonts are installed by default into -# "/usr/lpp/X11/lib/X11/fonts/Type1" and sym-linked to "/usr/lib/X11/fonts/Type1" +# +# Portions Copyright (c) 2014 IBM Corporation +# + +# This file references the standard Latin Type1 fonts from the AIX package +# X11.fnt.iso_T1 and the Unicode TrueType fonts from X11.fnt.ucs.ttf. They +# are located by default under "/usr/lpp/X11/lib/X11/fonts/{Type1,TrueType}" +# and sym-linked to "/usr/lib/X11/fonts/". # Version @@ -34,44 +39,381 @@ version=1 # Component Font Mappings -dialog.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1 -dialog.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1 -dialog.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1 -dialog.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1 +allfonts.iso10646-extB=-monotype-sansmonowtextb-medium-r-normal--*-%d-75-75-m-*-unicode-2 -dialoginput.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1 -dialoginput.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1 -dialoginput.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1 -dialoginput.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1 -sansserif.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1 -sansserif.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1 -sansserif.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1 -sansserif.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1 +dialog.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1 +dialog.plain.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.plain.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.plain.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.plain.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.plain.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.plain.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.plain.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.plain.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.plain.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.plain.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 -serif.plain.latin-1=-*-times new roman-medium-r-normal--*-%d-100-100-p-*-iso10646-1 -serif.bold.latin-1=-*-times new roman-bold-r-normal--*-%d-100-100-p-*-iso10646-1 -serif.italic.latin-1=-*-times new roman-medium-i-normal--*-%d-100-100-p-*-iso10646-1 -serif.bolditalic.latin-1=-*-times new roman-bold-i-normal--*-%d-100-100-p-*-iso10646-1 +dialog.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1 +dialog.bold.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.bold.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.bold.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.bold.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.bold.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.bold.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.bold.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.bold.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.bold.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.bold.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 -monospaced.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1 -monospaced.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1 -monospaced.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1 -monospaced.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1 +dialog.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1 +dialog.italic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.italic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.italic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.italic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.italic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.italic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.italic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.italic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.italic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.italic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialog.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1 +dialog.bolditalic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +dialog.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +dialog.bolditalic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialog.bolditalic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialog.bolditalic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialog.bolditalic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialog.bolditalic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialog.bolditalic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialog.bolditalic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialog.bolditalic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialog.bolditalic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.plain.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.plain.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.plain.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.plain.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.plain.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.plain.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.plain.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.plain.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.plain.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.plain.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.bold.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.bold.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.bold.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.bold.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.bold.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.bold.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.bold.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.bold.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.bold.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.bold.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.italic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.italic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.italic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.italic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.italic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.italic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.italic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.italic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.italic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.italic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +dialoginput.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1 +dialoginput.bolditalic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +dialoginput.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +dialoginput.bolditalic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +dialoginput.bolditalic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +dialoginput.bolditalic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +dialoginput.bolditalic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +dialoginput.bolditalic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +dialoginput.bolditalic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +dialoginput.bolditalic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +dialoginput.bolditalic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +dialoginput.bolditalic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.plain.latin-1=-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.plain.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.plain.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.plain.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.plain.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.plain.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.plain.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.plain.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.plain.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.plain.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.plain.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.bold.latin-1=-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.bold.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.bold.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.bold.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.bold.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.bold.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.bold.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.bold.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.bold.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.bold.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.bold.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.italic.latin-1=-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.italic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.italic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.italic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.italic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.italic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.italic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.italic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.italic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.italic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.italic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +sansserif.bolditalic.latin-1=-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1 +sansserif.bolditalic.thai=-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +sansserif.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +sansserif.bolditalic.japanese-x0208=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +sansserif.bolditalic.japanese-x0201=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +sansserif.bolditalic.japanese-udc=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +sansserif.bolditalic.japanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +sansserif.bolditalic.korean=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +sansserif.bolditalic.korean-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +sansserif.bolditalic.chinese=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +sansserif.bolditalic.chinese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +sansserif.bolditalic.taiwanese-iso10646=-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +serif.plain.latin-1=-*-times new roman-medium-r-normal--*-%d-100-100-p-*-iso8859-1 +serif.plain.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.plain.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.plain.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.plain.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.plain.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.plain.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.plain.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.plain.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.plain.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.plain.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +serif.bold.latin-1=-*-times new roman-bold-r-normal--*-%d-100-100-p-*-iso8859-1 +serif.bold.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.bold.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.bold.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.bold.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.bold.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.bold.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.bold.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.bold.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.bold.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.bold.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + + +serif.italic.latin-1=-*-times new roman-medium-i-normal--*-%d-100-100-p-*-iso8859-1 +serif.italic.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.italic.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.italic.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.italic.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.italic.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.italic.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.italic.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.italic.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.italic.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.italic.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +serif.bolditalic.latin-1=-*-times new roman-bold-i-normal--*-%d-100-100-p-*-iso8859-1 +serif.bolditalic.thai=-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0 +serif.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0 +serif.bolditalic.japanese-x0208=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +serif.bolditalic.japanese-x0201=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +serif.bolditalic.japanese-udc=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +serif.bolditalic.japanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +serif.bolditalic.korean=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +serif.bolditalic.korean-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +serif.bolditalic.chinese=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +serif.bolditalic.chinese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +serif.bolditalic.taiwanese-iso10646=-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.plain.latin-1=-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.plain.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.plain.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.plain.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.plain.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.plain.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.plain.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.plain.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.plain.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.plain.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.plain.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.plain.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.bold.latin-1=-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.bold.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.bold.ukranian-ibm1124=-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.bold.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.bold.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.bold.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.bold.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.bold.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.bold.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.bold.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.bold.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.bold.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.italic.latin-1=-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.italic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.italic.ukranian-ibm1124=-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.italic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.italic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.italic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.italic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.italic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.italic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.italic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.italic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.italic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 + +monospaced.bolditalic.latin-1=-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1 +monospaced.bolditalic.thai=-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0 +monospaced.bolditalic.ukranian-ibm1124=-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0 +monospaced.bolditalic.japanese-x0208=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0 +monospaced.bolditalic.japanese-x0201=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0 +monospaced.bolditalic.japanese-udc=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp +monospaced.bolditalic.japanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0 +monospaced.bolditalic.korean=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0 +monospaced.bolditalic.korean-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0 +monospaced.bolditalic.chinese=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0 +monospaced.bolditalic.chinese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0 +monospaced.bolditalic.taiwanese-iso10646=-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0 # Search Sequences sequence.allfonts=latin-1 +sequence.allfonts.UTF-8=latin-1,japanese-iso10646 +# Uk_UA +sequence.allfonts.x-IBM1124=latin-1,ukranian-ibm1124 +# Japanese +sequence.allfonts.x-IBM943C=latin-1,japanese-x0201,japanese-x0208,japanese-udc +sequence.allfonts.x-IBM29626C=latin-1,japanese-x0201,japanese-x0208,japanese-udc +sequence.allfonts.UTF-8.ja=japanese-iso10646,latin-1,iso10646-extB +# Chinese +sequence.allfonts.x-EUC_CN=latin-1,chinese +sequence.allfonts.GB18030=latin-1,chinese-iso10646,iso10646-extB +sequence.allfonts.UTF-8.zh.CN=latin-1,chinese-iso10646,iso10646-extB +# Taiwanese +sequence.allfonts.x-IBM964=latin-1,taiwanese-iso10646 +sequence.allfonts.Big5=latin-1,taiwanese-iso10646 +sequence.allfonts.UTF-8.zh.TW=latin-1,taiwanese-iso10646 +# Korean +sequence.allfonts.x-IBM970=latin-1,korean +sequence.allfonts.UTF-8.ko=latin-1,korean-iso10646 +# Thai +sequence.allfonts.TIS-620=latin-1,thai +sequence.allfonts.UTF-8.th=latin-1,thai +# fallback +sequence.fallback=thai,chinese-iso10646,taiwanese-iso10646,japanese-iso10646,korean-iso10646,iso10646-extB + +# Exclusion Ranges +exclusion.japanese-iso10646=0000-00ff + +# Font File Names +filename.-*-courier-medium-r-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/cour.pfa +filename.-*-courier-bold-r-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/courb.pfa +filename.-*-courier-medium-o-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/couri.pfa +filename.-*-courier-bold-o-normal--*-%d-100-100-m-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/courbi.pfa +filename.-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helv.pfa +filename.-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvb.pfa +filename.-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvi.pfa +filename.-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvbi.pfa +filename.-*-times_new_roman-medium-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnr.pfa +filename.-*-times_new_roman-bold-r-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrb.pfa +filename.-*-times_new_roman-medium-i-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnri.pfa +filename.-*-times_new_roman-bold-i-normal--*-%d-100-100-p-*-iso8859-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrbi.pfa + + +filename.-monotype-sansmonowtextb-medium-r-normal--*-%d-75-75-m-*-unicode-2=/usr/lpp/X11/lib/X11/fonts/TrueType/MTSanXBA.ttf + +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_k.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_k.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_s.ttf +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_t.ttf + +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdk.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdk.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansds.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansds.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdt.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0208.1983-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-jisx0201.1976-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ibm-udcjp=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_japan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_j.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ksc5601.1987-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_k.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_korea-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_k.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-gb2312.1980-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_s.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_china-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_s.ttf +filename.-monotype-sanswt-medium-r-normal--*-%d-75-75-*-*-ucs2.cjk_taiwan-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsans_t.ttf + +filename.-monotype-timesnewromanwt-medium-r-normal--*-%d-75-75-*-*-iso8859-15=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-monotype-sansmonowt-medium-r-normal--*-%d-75-75-*-*-iso8859-15=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf + +filename.-ibm-thaicourier-medium-r-normal--*-%d-75-75-m-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/courth.ttf +filename.-ibm-thaihelvetica-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/helvth.ttf +filename.-ibm-thaitimes-medium-r-normal--*-%d-75-75-p-*-ucs2.thai-0=/usr/lpp/X11/lib/X11/fonts/TrueType/timeth.ttf + +filename.-*-*-medium-r-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-bold-r-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-i-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-bold-i-normal--*-%d-*-*-p-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-r-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-bold-r-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-medium-i-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-bold-i-normal--*-%d-*-*-m-*-ibm-1046=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf + +filename.-*-*-medium-r-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-bold-r-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-i-normal--*-%d-75-75-p-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/tnrwt_j.ttf +filename.-*-*-medium-r-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-bold-r-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf +filename.-*-*-medium-i-normal--*-%d-75-75-m-*-ucs2.i18n-0=/usr/lpp/X11/lib/X11/fonts/TrueType/mtsansdj.ttf + +# AWT font path +awtfontpath.japanese-x0201=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.japanese-x0208=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.japanese-udc=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.japanese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.korean=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.korean-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.chinese=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.chinese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.taiwanese-iso10646=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.thai=/usr/lpp/X11/lib/X11/fonts/TrueType +awtfontpath.iso10646-extB=/usr/lpp/X11/lib/X11/fonts/TrueType -filename.-*-courier-medium-r-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/cour.pfa -filename.-*-courier-bold-r-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/courb.pfa -filename.-*-courier-medium-o-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/couri.pfa -filename.-*-courier-bold-o-normal--*-%d-100-100-m-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/courbi.pfa -filename.-*-helvetica-medium-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helv.pfa -filename.-*-helvetica-bold-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvb.pfa -filename.-*-helvetica-medium-o-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvi.pfa -filename.-*-helvetica-bold-o-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/helvbi.pfa -filename.-*-times_new_roman-medium-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnr.pfa -filename.-*-times_new_roman-bold-r-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrb.pfa -filename.-*-times_new_roman-medium-i-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnri.pfa -filename.-*-times_new_roman-bold-i-normal--*-%d-100-100-p-*-iso10646-1=/usr/lpp/X11/lib/X11/fonts/Type1/tnrbi.pfa diff --git a/jdk/make/data/tzdata/VERSION b/jdk/make/data/tzdata/VERSION index c735be51ca1..5e925ada8df 100644 --- a/jdk/make/data/tzdata/VERSION +++ b/jdk/make/data/tzdata/VERSION @@ -1,24 +1,24 @@ # # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# +# # This code is free software; you can redistribute 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. # -tzdata2014c +tzdata2014g diff --git a/jdk/make/data/tzdata/africa b/jdk/make/data/tzdata/africa index 6f1a1471e0c..aa91f365ce1 100644 --- a/jdk/make/data/tzdata/africa +++ b/jdk/make/data/tzdata/africa @@ -21,13 +21,13 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -#
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-02-21):
 #
@@ -49,8 +49,8 @@
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# .
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
@@ -58,13 +58,13 @@
 # Previous editions of this database used WAT, CAT, SAT, and EAT
 # for +0:00 through +3:00, respectively,
 # but Mark R V Murray reports that
-# `SAST' is the official abbreviation for +2:00 in the country of South Africa,
-# `CAT' is commonly used for +2:00 in countries north of South Africa, and
-# `WAT' is probably the best name for +1:00, as the common phrase for
-# the area that includes Nigeria is ``West Africa''.
-# He has heard of ``Western Sahara Time'' for +0:00 but can find no reference.
+# 'SAST' is the official abbreviation for +2:00 in the country of South Africa,
+# 'CAT' is commonly used for +2:00 in countries north of South Africa, and
+# 'WAT' is probably the best name for +1:00, as the common phrase for
+# the area that includes Nigeria is "West Africa".
+# He has heard of "Western Sahara Time" for +0:00 but can find no reference.
 #
-# To make things confusing, `WAT' seems to have been used for -1:00 long ago;
+# To make things confusing, 'WAT' seems to have been used for -1:00 long ago;
 # I'd guess that this was because people needed _some_ name for -1:00,
 # and at the time, far west Africa was the only major land area in -1:00.
 # This usage is now obsolete, as the last use of -1:00 on the African
@@ -77,7 +77,7 @@
 #	 2:00	SAST	South Africa Standard Time
 # and Murray suggests the following abbreviation:
 #	 1:00	WAT	West Africa Time
-# I realize that this leads to `WAT' being used for both -1:00 and 1:00
+# I realize that this leads to 'WAT' being used for both -1:00 and 1:00
 # for times before 1976, but this is the best I can think of
 # until we get more information.
 #
@@ -117,9 +117,9 @@ Rule	Algeria	1980	only	-	Oct	31	 2:00	0	-
 # Shanks & Pottenger give 0:09:20 for Paris Mean Time; go with Howse's
 # more precise 0:09:21.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15 0:01
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
-			0:00	Algeria	WE%sT	1940 Feb 25 2:00
+Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15  0:01
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
+			0:00	Algeria	WE%sT	1940 Feb 25  2:00
 			1:00	Algeria	CE%sT	1946 Oct  7
 			0:00	-	WET	1956 Jan 29
 			1:00	-	CET	1963 Apr 14
@@ -129,18 +129,8 @@ Zone	Africa/Algiers	0:12:12 -	LMT	1891 Mar 15 0:01
 			1:00	-	CET
 
 # Angola
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Luanda	0:52:56	-	LMT	1892
-			0:52:04	-	AOT	1911 May 26 # Angola Time
-			1:00	-	WAT
-
 # Benin
-# Whitman says they switched to 1:00 in 1946, not 1934;
-# go with Shanks & Pottenger.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Porto-Novo	0:10:28	-	LMT	1912
-			0:00	-	GMT	1934 Feb 26
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Botswana
 # From Paul Eggert (2013-02-21):
@@ -149,14 +139,12 @@ Zone Africa/Porto-Novo	0:10:28	-	LMT	1912
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Gaborone	1:43:40 -	LMT	1885
 			1:30	-	SAST	1903 Mar
-			2:00	-	CAT	1943 Sep 19 2:00
-			2:00	1:00	CAST	1944 Mar 19 2:00
+			2:00	-	CAT	1943 Sep 19  2:00
+			2:00	1:00	CAST	1944 Mar 19  2:00
 			2:00	-	CAT
 
 # Burkina Faso
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Ouagadougou	-0:06:04 -	LMT	1912
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Burundi
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -164,52 +152,60 @@ Zone Africa/Bujumbura	1:57:28	-	LMT	1890
 			2:00	-	CAT
 
 # Cameroon
-# Whitman says they switched to 1:00 in 1920; go with Shanks & Pottenger.
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Douala	0:38:48	-	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Cape Verde
+#
+# Shanks gives 1907 for the transition to CVT.
+# Perhaps the 1911-05-26 Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# merely made it official?
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/Cape_Verde -1:34:04 -	LMT	1907			# Praia
+Zone Atlantic/Cape_Verde -1:34:04 -	LMT	1907        # Praia
 			-2:00	-	CVT	1942 Sep
 			-2:00	1:00	CVST	1945 Oct 15
-			-2:00	-	CVT	1975 Nov 25 2:00
+			-2:00	-	CVT	1975 Nov 25  2:00
 			-1:00	-	CVT
 
 # Central African Republic
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bangui	1:14:20	-	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Chad
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Ndjamena	1:00:12 -	LMT	1912
+Zone	Africa/Ndjamena	1:00:12 -	LMT	1912        # N'Djamena
 			1:00	-	WAT	1979 Oct 14
 			1:00	1:00	WAST	1980 Mar  8
 			1:00	-	WAT
 
 # Comoros
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Comoro	2:53:04 -	LMT	1911 Jul   # Moroni, Gran Comoro
+Zone	Indian/Comoro	2:53:04 -	LMT	1911 Jul # Moroni, Gran Comoro
 			3:00	-	EAT
 
-# Democratic Republic of Congo
+# Democratic Republic of the Congo
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Kinshasa	1:01:12 -	LMT	1897 Nov 9
-			1:00	-	WAT
 Zone Africa/Lubumbashi	1:49:52 -	LMT	1897 Nov 9
 			2:00	-	CAT
+# The above is for the eastern part; see Africa/Lagos for the western part.
 
 # Republic of the Congo
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Brazzaville	1:01:08 -	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
-# Cote D'Ivoire
+# Côte d'Ivoire / Ivory Coast
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Abidjan	-0:16:08 -	LMT	1912
 			 0:00	-	GMT
+Link Africa/Abidjan Africa/Bamako	# Mali
+Link Africa/Abidjan Africa/Banjul	# Gambia
+Link Africa/Abidjan Africa/Conakry	# Guinea
+Link Africa/Abidjan Africa/Dakar	# Senegal
+Link Africa/Abidjan Africa/Freetown	# Sierra Leone
+Link Africa/Abidjan Africa/Lome		# Togo
+Link Africa/Abidjan Africa/Nouakchott	# Mauritania
+Link Africa/Abidjan Africa/Ouagadougou	# Burkina Faso
+Link Africa/Abidjan Africa/Sao_Tome	# São Tomé and Príncipe
+Link Africa/Abidjan Atlantic/St_Helena	# St Helena
 
 # Djibouti
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -254,30 +250,26 @@ Rule	Egypt	1990	1994	-	May	 1	1:00	1:00	S
 # Egyptians would approve the cancellation."
 #
 # Egypt to cancel daylight saving time
-# 
 # http://www.almasryalyoum.com/en/node/407168
-# 
 # or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_egypt04.html
-# 
 Rule	Egypt	1995	2010	-	Apr	lastFri	 0:00s	1:00	S
-Rule	Egypt	1995	2005	-	Sep	lastThu	23:00s	0	-
+Rule	Egypt	1995	2005	-	Sep	lastThu	24:00	0	-
 # From Steffen Thorsen (2006-09-19):
 # The Egyptian Gazette, issue 41,090 (2006-09-18), page 1, reports:
 # Egypt will turn back clocks by one hour at the midnight of Thursday
 # after observing the daylight saving time since May.
 # http://news.gom.com.eg/gazette/pdf/2006/09/18/01.pdf
-Rule	Egypt	2006	only	-	Sep	21	23:00s	0	-
+Rule	Egypt	2006	only	-	Sep	21	24:00	0	-
 # From Dirk Losch (2007-08-14):
 # I received a mail from an airline which says that the daylight
 # saving time in Egypt will end in the night of 2007-09-06 to 2007-09-07.
-# From Jesper Norgaard Welen (2007-08-15): [The following agree:]
+# From Jesper Nørgaard Welen (2007-08-15): [The following agree:]
 # http://www.nentjes.info/Bill/bill5.htm
 # http://www.timeanddate.com/worldclock/city.html?n=53
 # From Steffen Thorsen (2007-09-04): The official information...:
 # http://www.sis.gov.eg/En/EgyptOnline/Miscellaneous/000002/0207000000000000001580.htm
-Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
+Rule	Egypt	2007	only	-	Sep	Thu>=1	24:00	0	-
 # From Abdelrahman Hassan (2007-09-06):
 # Due to the Hijri (lunar Islamic calendar) year being 11 days shorter
 # than the year of the Gregorian calendar, Ramadan shifts earlier each
@@ -311,15 +303,9 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 #
 # timeanddate[2] and another site I've found[3] also support that.
 #
-# [1] 
-# https://bugzilla.redhat.com/show_bug.cgi?id=492263
-# 
-# [2] 
-# http://www.timeanddate.com/worldclock/clockchange.html?n=53
-# 
-# [3] 
-# http://wwp.greenwichmeantime.com/time-zone/africa/egypt/
-# 
+# [1] https://bugzilla.redhat.com/show_bug.cgi?id=492263
+# [2] http://www.timeanddate.com/worldclock/clockchange.html?n=53
+# [3] http://wwp.greenwichmeantime.com/time-zone/africa/egypt/
 
 # From Arthur David Olson (2009-04-20):
 # In 2009 (and for the next several years), Ramadan ends before the fourth
@@ -329,14 +315,10 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 # From Steffen Thorsen (2009-08-11):
 # We have been able to confirm the August change with the Egyptian Cabinet
 # Information and Decision Support Center:
-# 
 # http://www.timeanddate.com/news/time/egypt-dst-ends-2009.html
-# 
 #
 # The Middle East News Agency
-# 
 # http://www.mena.org.eg/index.aspx
-# 
 # also reports "Egypt starts winter time on August 21"
 # today in article numbered "71, 11/08/2009 12:25 GMT."
 # Only the title above is available without a subscription to their service,
@@ -344,19 +326,14 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 # (at least today).
 
 # From Alexander Krivenyshev (2010-07-20):
-# According to News from Egypt -  Al-Masry Al-Youm Egypt's cabinet has
+# According to News from Egypt - Al-Masry Al-Youm Egypt's cabinet has
 # decided that Daylight Saving Time will not be used in Egypt during
 # Ramadan.
 #
 # Arabic translation:
-# "Clocks to go back during Ramadan--and then forward again"
-# 
+# "Clocks to go back during Ramadan - and then forward again"
 # http://www.almasryalyoum.com/en/news/clocks-go-back-during-ramadan-and-then-forward-again
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_egypt02.html
-# 
 
 # From Ahmad El-Dardiry (2014-05-07):
 # Egypt is to change back to Daylight system on May 15
@@ -365,46 +342,77 @@ Rule	Egypt	2007	only	-	Sep	Thu>=1	23:00s	0	-
 # From Gunther Vermier (2015-05-13):
 # our Egypt office confirms that the change will be at 15 May "midnight" (24:00)
 
-# From Paul Eggert (2014-05-13):
+# From Imed Chihi (2014-06-04):
+# We have finally "located" a precise official reference about the DST changes
+# in Egypt.  The Ministers Cabinet decision is explained at
+# http://www.cabinet.gov.eg/Media/CabinetMeetingsDetails.aspx?id=347 ...
+# [T]his (Arabic) site is not accessible outside Egypt, but the page ...
+# translates into: "With regard to daylight saving time, it is scheduled to
+# take effect at exactly twelve o'clock this evening, Thursday, 15 MAY 2014,
+# to be suspended by twelve o'clock on the evening of Thursday, 26 JUN 2014,
+# and re-established again at the end of the month of Ramadan, at twelve
+# o'clock on the evening of Thursday, 31 JUL 2014."  This statement has been
+# reproduced by other (more accessible) sites[, e.g.,]...
+# http://elgornal.net/news/news.aspx?id=4699258
+
+# From Paul Eggert (2014-06-04):
 # Sarah El Deeb and Lee Keath of AP report that the Egyptian government says
 # the change is because of blackouts in Cairo, even though Ahram Online (cited
-# above) says DST had no affect on electricity consumption.  The AP story says
-# DST will not be observed during Ramadan.  There is no information about when
-# DST will end.  See:
+# above) says DST had no affect on electricity consumption.  There is
+# no information about when DST will end this fall.  See:
 # http://abcnews.go.com/International/wireStory/el-sissi-pushes-egyptians-line-23614833
 #
-# For now, guess that later transitions will use 2010's rules, and that
-# Egypt will agree with Morocco (see below) about the date Ramadan starts and
-# ends, though (unlike Morocco) it will switch at 00:00 standard time.  In
-# Egypt the spring-forward transitions are removed for 2020-2022, when the
-# guessed spring-forward date falls during the estimated Ramadan, and all
-# transitions removed for 2023-2038, where the estimated Ramadan falls entirely
-# outside the guessed daylight-saving time.  Ramadan intrudes on the guessed
-# DST starting in 2039, but that's beyond our somewhat-arbitrary cutoff.
-
-Rule	Egypt	2008	only	-	Aug	lastThu	23:00s	0	-
-Rule	Egypt	2009	only	-	Aug	20	23:00s	0	-
-Rule	Egypt	2010	only	-	Aug	11	0:00	0	-
-Rule	Egypt	2010	only	-	Sep	10	0:00	1:00	S
-Rule	Egypt	2010	only	-	Sep	lastThu	23:00s	0	-
+# For now, guess that later spring and fall transitions will use
+# 2010's rules, and guess that Egypt will switch to standard time at
+# 24:00 the last Thursday before Ramadan, and back to DST at 00:00 the
+# first Friday after Ramadan.  To implement this,
+# transition dates for 2015 through 2037 were determined by running
+# the following program under GNU Emacs 24.3, with the results integrated
+# by hand into the table below.  Ramadan again intrudes on the guessed
+# DST starting in 2038, but that's beyond our somewhat-arbitrary cutoff.
+# (let ((islamic-year 1436))
+#   (while (< islamic-year 1460)
+#     (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
+#           (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
+#           (friday 5))
+#       (while (/= friday (mod a 7))
+#         (setq a (1- a)))
+#       (while (/= friday (mod b 7))
+#         (setq b (1+ b)))
+#       (setq a (1- a))
+#       (setq b (1- b))
+#       (setq a (calendar-gregorian-from-absolute a))
+#       (setq b (calendar-gregorian-from-absolute b))
+#       (insert
+#        (format
+#         (concat "Rule\tEgypt\t%d\tonly\t-\t%s\t%2d\t24:00\t0\t-\n"
+#                 "Rule\tEgypt\t%d\tonly\t-\t%s\t%2d\t24:00\t1:00\tS\n")
+#         (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
+#         (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
+#     (setq islamic-year (+ 1 islamic-year))))
+Rule	Egypt	2008	only	-	Aug	lastThu	24:00	0	-
+Rule	Egypt	2009	only	-	Aug	20	24:00	0	-
+Rule	Egypt	2010	only	-	Aug	10	24:00	0	-
+Rule	Egypt	2010	only	-	Sep	 9	24:00	1:00	S
+Rule	Egypt	2010	only	-	Sep	lastThu	24:00	0	-
 Rule	Egypt	2014	only	-	May	15	24:00	1:00	S
-Rule	Egypt	2014	only	-	Jun	29	 0:00s	0	-
-Rule	Egypt	2014	only	-	Jul	29	 0:00s	1:00	S
-Rule	Egypt	2014	max	-	Sep	lastThu	23:00s	0	-
+Rule	Egypt	2014	only	-	Jun	26	24:00	0	-
+Rule	Egypt	2014	only	-	Jul	31	24:00	1:00	S
+Rule	Egypt	2014	max	-	Sep	lastThu	24:00	0	-
 Rule	Egypt	2015	2019	-	Apr	lastFri	 0:00s	1:00	S
-Rule	Egypt	2015	only	-	Jun	18	 0:00s	0	-
-Rule	Egypt	2015	only	-	Jul	18	 0:00s	1:00	S
-Rule	Egypt	2016	only	-	Jun	 7	 0:00s	0	-
-Rule	Egypt	2016	only	-	Jul	 7	 0:00s	1:00	S
-Rule	Egypt	2017	only	-	May	27	 0:00s	0	-
-Rule	Egypt	2017	only	-	Jun	26	 0:00s	1:00	S
-Rule	Egypt	2018	only	-	May	16	 0:00s	0	-
-Rule	Egypt	2018	only	-	Jun	15	 0:00s	1:00	S
-Rule	Egypt	2019	only	-	May	 6	 0:00s	0	-
-Rule	Egypt	2019	only	-	Jun	 5	 0:00s	1:00	S
-Rule	Egypt	2020	only	-	May	24	 0:00s	1:00	S
-Rule	Egypt	2021	only	-	May	13	 0:00s	1:00	S
-Rule	Egypt	2022	only	-	May	 3	 0:00s	1:00	S
+Rule	Egypt	2015	only	-	Jun	11	24:00	0	-
+Rule	Egypt	2015	only	-	Jul	23	24:00	1:00	S
+Rule	Egypt	2016	only	-	Jun	 2	24:00	0	-
+Rule	Egypt	2016	only	-	Jul	 7	24:00	1:00	S
+Rule	Egypt	2017	only	-	May	25	24:00	0	-
+Rule	Egypt	2017	only	-	Jun	29	24:00	1:00	S
+Rule	Egypt	2018	only	-	May	10	24:00	0	-
+Rule	Egypt	2018	only	-	Jun	14	24:00	1:00	S
+Rule	Egypt	2019	only	-	May	 2	24:00	0	-
+Rule	Egypt	2019	only	-	Jun	 6	24:00	1:00	S
+Rule	Egypt	2020	only	-	May	28	24:00	1:00	S
+Rule	Egypt	2021	only	-	May	13	24:00	1:00	S
+Rule	Egypt	2022	only	-	May	 5	24:00	1:00	S
 Rule	Egypt	2023	max	-	Apr	lastFri	 0:00s	1:00	S
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -412,60 +420,63 @@ Zone	Africa/Cairo	2:05:09 -	LMT	1900 Oct
 			2:00	Egypt	EE%sT
 
 # Equatorial Guinea
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Malabo	0:35:08 -	LMT	1912
-			0:00	-	GMT	1963 Dec 15
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Eritrea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Asmara	2:35:32 -	LMT	1870
-			2:35:32	-	AMT	1890	      # Asmara Mean Time
-			2:35:20	-	ADMT	1936 May 5    # Adis Dera MT
+			2:35:32	-	AMT	1890        # Asmara Mean Time
+			2:35:20	-	ADMT	1936 May  5 # Adis Dera MT
 			3:00	-	EAT
 
 # Ethiopia
-# From Paul Eggert (2006-03-22):
-# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time zones
-# between 1870 and 1890, and that they merged to 38E50 (2:35:20) in 1890.
-# We'll guess that 38E50 is for Adis Dera.
+# From Paul Eggert (2014-07-31):
+# Like the Swahili of Kenya and Tanzania, many Ethiopians keep a
+# 12-hour clock starting at our 06:00, so their "8 o'clock" is our
+# 02:00 or 14:00.  Keep this in mind when you ask the time in Amharic.
+#
+# Shanks & Pottenger write that Ethiopia had six narrowly-spaced time
+# zones between 1870 and 1890, that they merged to 38E50 (2:35:20) in
+# 1890, and that they switched to 3:00 on 1936-05-05.  Perhaps 38E50
+# was for Adis Dera.  Quite likely the Shanks data entries are wrong
+# anyway.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Addis_Ababa	2:34:48 -	LMT	1870
-			2:35:20	-	ADMT	1936 May 5    # Adis Dera MT
+			2:35:20	-	ADMT	1936 May  5 # Adis Dera MT
 			3:00	-	EAT
 
 # Gabon
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Libreville	0:37:48 -	LMT	1912
-			1:00	-	WAT
+# See Africa/Lagos.
 
 # Gambia
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Banjul	-1:06:36 -	LMT	1912
-			-1:06:36 -	BMT	1935	# Banjul Mean Time
-			-1:00	-	WAT	1964
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Ghana
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Whitman says DST was observed from 1931 to ``the present'';
-# go with Shanks & Pottenger.
-Rule	Ghana	1936	1942	-	Sep	 1	0:00	0:20	GHST
-Rule	Ghana	1936	1942	-	Dec	31	0:00	0	GMT
+# Whitman says DST was observed from 1931 to "the present";
+# Shanks & Pottenger say 1936 to 1942;
+# and September 1 to January 1 is given by:
+# Scott Keltie J, Epstein M (eds), The Statesman's Year-Book,
+# 57th ed. Macmillan, London (1920), OCLC 609408015, pp xxviii.
+# For lack of better info, assume DST was observed from 1920 to 1942.
+Rule	Ghana	1920	1942	-	Sep	 1	0:00	0:20	GHST
+Rule	Ghana	1920	1942	-	Dec	31	0:00	0	GMT
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Accra	-0:00:52 -	LMT	1918
 			 0:00	Ghana	%s
 
 # Guinea
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Conakry	-0:54:52 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Guinea-Bissau
+#
+# Shanks gives 1911-05-26 for the transition to WAT,
+# evidently confusing the date of the Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# with the date that it took effect, namely 1912-01-01.
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bissau	-1:02:20 -	LMT	1911 May 26
+Zone	Africa/Bissau	-1:02:20 -	LMT	1912 Jan  1
 			-1:00	-	WAT	1975
 			 0:00	-	GMT
 
@@ -480,8 +491,8 @@ Zone	Africa/Nairobi	2:27:16	-	LMT	1928 Jul
 # Lesotho
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Maseru	1:50:00 -	LMT	1903 Mar
-			2:00	-	SAST	1943 Sep 19 2:00
-			2:00	1:00	SAST	1944 Mar 19 2:00
+			2:00	-	SAST	1943 Sep 19  2:00
+			2:00	1:00	SAST	1944 Mar 19  2:00
 			2:00	-	SAST
 
 # Liberia
@@ -549,11 +560,11 @@ Zone	Africa/Tripoli	0:52:44 -	LMT	1920
 			2:00	-	EET	1982
 			1:00	Libya	CE%sT	1990 May  4
 # The 1996 and 1997 entries are from Shanks & Pottenger;
-# the IATA SSIM data contain some obvious errors.
+# the IATA SSIM data entries contain some obvious errors.
 			2:00	-	EET	1996 Sep 30
 			1:00	Libya	CE%sT	1997 Oct  4
-			2:00	-	EET	2012 Nov 10 2:00
-			1:00	Libya	CE%sT	2013 Oct 25 2:00
+			2:00	-	EET	2012 Nov 10  2:00
+			1:00	Libya	CE%sT	2013 Oct 25  2:00
 			2:00	-	EET
 
 # Madagascar
@@ -569,18 +580,8 @@ Zone	Africa/Blantyre	2:20:00 -	LMT	1903 Mar
 			2:00	-	CAT
 
 # Mali
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Bamako	-0:32:00 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960 Jun 20
-			 0:00	-	GMT
-
 # Mauritania
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
-			 0:00	-	GMT	1934 Feb 26
-			-1:00	-	WAT	1960 Nov 28
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Mauritius
 
@@ -604,9 +605,7 @@ Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
 
 # From Steffen Thorsen (2008-07-10):
 # According to
-# 
 # http://www.lexpress.mu/display_article.php?news_id=111216
-# 
 # (in French), Mauritius will start and end their DST a few days earlier
 # than previously announced (2008-11-01 to 2009-03-31).  The new start
 # date is 2008-10-26 at 02:00 and the new end date is 2009-03-27 (no time
@@ -621,22 +620,17 @@ Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
 
 # From Alex Krivenyshev (2008-07-11):
 # Seems that English language article "The revival of daylight saving
-# time:  Energy conservation?"-# No. 16578 (07/11/2008) was originally
+# time: Energy conservation?"-# No. 16578 (07/11/2008) was originally
 # published on Monday, June 30, 2008...
 #
 # I guess that article in French "Le gouvernement avance l'introduction
-# de l'heure d'ete" stating that DST in Mauritius starting on October 26
-# and ending on March 27, 2009 is the most recent one.
-# ...
-# 
+# de l'heure d'été" stating that DST in Mauritius starting on October 26
+# and ending on March 27, 2009 is the most recent one....
 # http://www.worldtimezone.com/dst_news/dst_news_mauritius02.html
-# 
 
 # From Riad M. Hossen Ally (2008-08-03):
 # The Government of Mauritius weblink
-# 
 # http://www.gov.mu/portal/site/pmosite/menuitem.4ca0efdee47462e7440a600248a521ca/?content_id=4728ca68b2a5b110VgnVCM1000000a04a8c0RCRD
-# 
 # Cabinet Decision of July 18th, 2008 states as follows:
 #
 # 4. ...Cabinet has agreed to the introduction into the National Assembly
@@ -646,33 +640,25 @@ Zone Africa/Nouakchott	-1:03:48 -	LMT	1912
 # States of America. It will start at two o'clock in the morning on the
 # last Sunday of October and will end at two o'clock in the morning on
 # the last Sunday of March the following year. The summer time for the
-# year 2008 - 2009 will, therefore, be effective as from 26 October 2008
+# year 2008-2009 will, therefore, be effective as from 26 October 2008
 # and end on 29 March 2009.
 
 # From Ed Maste (2008-10-07):
 # THE TIME BILL (No. XXVII of 2008) Explanatory Memorandum states the
 # beginning / ending of summer time is 2 o'clock standard time in the
 # morning of the last Sunday of October / last Sunday of March.
-# 
 # http://www.gov.mu/portal/goc/assemblysite/file/bill2708.pdf
-# 
 
 # From Steffen Thorsen (2009-06-05):
 # According to several sources, Mauritius will not continue to observe
 # DST the coming summer...
 #
 # Some sources, in French:
-# 
 # http://www.defimedia.info/news/946/Rashid-Beebeejaun-:-%C2%AB-L%E2%80%99heure-d%E2%80%99%C3%A9t%C3%A9-ne-sera-pas-appliqu%C3%A9e-cette-ann%C3%A9e-%C2%BB
-# 
-# 
 # http://lexpress.mu/Story/3398~Beebeejaun---Les-objectifs-d-%C3%A9conomie-d-%C3%A9nergie-de-l-heure-d-%C3%A9t%C3%A9-ont-%C3%A9t%C3%A9-atteints-
-# 
 #
 # Our wrap-up:
-# 
 # http://www.timeanddate.com/news/time/mauritius-dst-will-not-repeat.html
-# 
 
 # From Arthur David Olson (2009-07-11):
 # The "mauritius-dst-will-not-repeat" wrapup includes this:
@@ -685,18 +671,18 @@ Rule Mauritius	1983	only	-	Mar	21	0:00	0	-
 Rule Mauritius	2008	only	-	Oct	lastSun	2:00	1:00	S
 Rule Mauritius	2009	only	-	Mar	lastSun	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Indian/Mauritius	3:50:00 -	LMT	1907		# Port Louis
+Zone Indian/Mauritius	3:50:00 -	LMT	1907 # Port Louis
 			4:00 Mauritius	MU%sT	# Mauritius Time
 # Agalega Is, Rodriguez
 # no information; probably like Indian/Mauritius
 
 # Mayotte
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
+Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul # Mamoutzou
 			3:00	-	EAT
 
 # Morocco
-# See the `europe' file for Spanish Morocco (Africa/Ceuta).
+# See the 'europe' file for Spanish Morocco (Africa/Ceuta).
 
 # From Alex Krivenyshev (2008-05-09):
 # Here is an article that Morocco plan to introduce Daylight Saving Time between
@@ -704,60 +690,44 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 #
 # "... Morocco is to save energy by adjusting its clock during summer so it will
 # be one hour ahead of GMT between 1 June and 27 September, according to
-# Communication Minister and Gov ernment Spokesman, Khalid Naciri...."
+# Communication Minister and Government Spokesman, Khalid Naciri...."
 #
-# 
 # http://www.worldtimezone.net/dst_news/dst_news_morocco01.html
-# 
-# OR
-# 
 # http://en.afrik.com/news11892.html
-# 
 
 # From Alex Krivenyshev (2008-05-09):
-# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe Presse:
-# 
+# The Morocco time change can be confirmed on Morocco web site Maghreb Arabe
+# Presse:
 # http://www.map.ma/eng/sections/box3/morocco_shifts_to_da/view
-# 
 #
 # Morocco shifts to daylight time on June 1st through September 27, Govt.
 # spokesman.
 
 # From Patrice Scattolin (2008-05-09):
 # According to this article:
-# 
 # http://www.avmaroc.com/actualite/heure-dete-comment-a127896.html
-# 
-# (and republished here:
-# 
-# http://www.actu.ma/heure-dete-comment_i127896_0.html
-# 
-# )
-# the changes occurs at midnight:
+# (and republished here: )
+# the changes occur at midnight:
 #
-# saturday night may 31st at midnight (which in french is to be
-# intrepreted as the night between saturday and sunday)
-# sunday night the 28th  at midnight
+# Saturday night May 31st at midnight (which in French is to be
+# interpreted as the night between Saturday and Sunday)
+# Sunday night the 28th at midnight
 #
-# Seeing that the 28th is monday, I am guessing that she intends to say
-# the midnight of the 28th which is the midnight between sunday and
-# monday, which jives with other sources that say that it's inclusive
-# june1st to sept 27th.
+# Seeing that the 28th is Monday, I am guessing that she intends to say
+# the midnight of the 28th which is the midnight between Sunday and
+# Monday, which jives with other sources that say that it's inclusive
+# June 1st to Sept 27th.
 #
 # The decision was taken by decree *2-08-224 *but I can't find the decree
 # published on the web.
 #
 # It's also confirmed here:
-# 
 # http://www.maroc.ma/NR/exeres/FACF141F-D910-44B0-B7FA-6E03733425D1.htm
-# 
-# on a government portal as being  between june 1st and sept 27th (not yet
-# posted in english).
+# on a government portal as being between June 1st and Sept 27th (not yet
+# posted in English).
 #
-# The following google query will generate many relevant hits:
-# 
+# The following Google query will generate many relevant hits:
 # http://www.google.com/search?hl=en&q=Conseil+de+gouvernement+maroc+heure+avance&btnG=Search
-# 
 
 # From Steffen Thorsen (2008-08-27):
 # Morocco will change the clocks back on the midnight between August 31
@@ -765,47 +735,32 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 # of September:
 #
 # One article about it (in French):
-# 
 # http://www.menara.ma/fr/Actualites/Maroc/Societe/ci.retour_a_l_heure_gmt_a_partir_du_dimanche_31_aout_a_minuit_officiel_.default
-# 
 #
 # We have some further details posted here:
-# 
 # http://www.timeanddate.com/news/time/morocco-ends-dst-early-2008.html
-# 
 
 # From Steffen Thorsen (2009-03-17):
 # Morocco will observe DST from 2009-06-01 00:00 to 2009-08-21 00:00 according
 # to many sources, such as
-# 
 # http://news.marweb.com/morocco/entertainment/morocco-daylight-saving.html
-# 
-# 
 # http://www.medi1sat.ma/fr/depeche.aspx?idp=2312
-# 
 # (French)
 #
 # Our summary:
-# 
 # http://www.timeanddate.com/news/time/morocco-starts-dst-2009.html
-# 
 
 # From Alexander Krivenyshev (2009-03-17):
 # Here is a link to official document from Royaume du Maroc Premier Ministre,
-# Ministere de la Modernisation des Secteurs Publics
+# Ministère de la Modernisation des Secteurs Publics
 #
 # Under Article 1 of Royal Decree No. 455-67 of Act 23 safar 1387 (2 june 1967)
 # concerning the amendment of the legal time, the Ministry of Modernization of
 # Public Sectors announced that the official time in the Kingdom will be
 # advanced 60 minutes from Sunday 31 May 2009 at midnight.
 #
-# 
 # http://www.mmsp.gov.ma/francais/Actualites_fr/PDF_Actualites_Fr/HeureEte_FR.pdf
-# 
-#
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_morocco03.html
-# 
 
 # From Steffen Thorsen (2010-04-13):
 # Several news media in Morocco report that the Ministry of Modernization
@@ -813,51 +768,33 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 # 2010-05-02 to 2010-08-08.
 #
 # Example:
-# 
 # http://www.lavieeco.com/actualites/4099-le-maroc-passera-a-l-heure-d-ete-gmt1-le-2-mai.html
-# 
 # (French)
 # Our page:
-# 
 # http://www.timeanddate.com/news/time/morocco-starts-dst-2010.html
-# 
 
 # From Dan Abitol (2011-03-30):
 # ...Rules for Africa/Casablanca are the following (24h format)
-# The 3rd april 2011 at 00:00:00, [it] will be 3rd april 1:00:00
-# The 31th july 2011 at 00:59:59,  [it] will be 31th July 00:00:00
+# The 3rd April 2011 at 00:00:00, [it] will be 3rd April 01:00:00
+# The 31st July 2011 at 00:59:59, [it] will be 31st July 00:00:00
 # ...Official links of change in morocco
 # The change was broadcast on the FM Radio
 # I ve called ANRT (telecom regulations in Morocco) at
 # +212.537.71.84.00
-# 
 # http://www.anrt.net.ma/fr/
-# 
 # They said that
-# 
 # http://www.map.ma/fr/sections/accueil/l_heure_legale_au_ma/view
-# 
 # is the official publication to look at.
 # They said that the decision was already taken.
 #
 # More articles in the press
-# 
-# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-lev
-# 
-# e.html
-# 
+# http://www.yabiladi.com/articles/details/5058/secret-l-heure-d-ete-maroc-leve.html
 # http://www.lematin.ma/Actualite/Express/Article.asp?id=148923
-# 
-# 
 # http://www.lavieeco.com/actualite/Le-Maroc-passe-sur-GMT%2B1-a-partir-de-dim
-# anche-prochain-5538.html
-# 
 
 # From Petr Machata (2011-03-30):
 # They have it written in English here:
-# 
 # http://www.map.ma/eng/sections/home/morocco_to_spring_fo/view
-# 
 #
 # It says there that "Morocco will resume its standard time on July 31,
 # 2011 at midnight." Now they don't say whether they mean midnight of
@@ -865,20 +802,16 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 # also been like that in the past.
 
 # From Alexander Krivenyshev (2012-03-09):
-# According to Infomédiaire web site from Morocco (infomediaire.ma),
-# on March 9, 2012, (in French) Heure légale:
-# Le Maroc adopte officiellement l'heure d'été
-# 
+# According to Infomédiaire web site from Morocco (infomediaire.ma),
+# on March 9, 2012, (in French) Heure légale:
+# Le Maroc adopte officiellement l'heure d'été
 # http://www.infomediaire.ma/news/maroc/heure-l%C3%A9gale-le-maroc-adopte-officiellement-lheure-d%C3%A9t%C3%A9
-# 
 # Governing Council adopted draft decree, that Morocco DST starts on
 # the last Sunday of March (March 25, 2012) and ends on
 # last Sunday of September (September 30, 2012)
 # except the month of Ramadan.
 # or (brief)
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_morocco06.html
-# 
 
 # From Arthur David Olson (2012-03-10):
 # The infomediaire.ma source indicates that the system is to be in
@@ -889,17 +822,13 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 
 # From Christophe Tropamer (2012-03-16):
 # Seen Morocco change again:
-# 
 # http://www.le2uminutes.com/actualite.php
-# 
-# "...à partir du dernier dimance d'avril et non fins mars,
-# comme annoncé précédemment."
+# "...à partir du dernier dimanche d'avril et non fins mars,
+# comme annoncé précédemment."
 
 # From Milamber Space Network (2012-07-17):
 # The official return to GMT is announced by the Moroccan government:
-# 
 # http://www.mmsp.gov.ma/fr/actualites.aspx?id=288 [in French]
-# 
 #
 # Google translation, lightly edited:
 # Back to the standard time of the Kingdom (GMT)
@@ -917,7 +846,7 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 # announced a bit in advance.  On 2012-07-11 the Moroccan government
 # announced that year's Ramadan daylight-saving transitions would be
 # 2012-07-20 and 2012-08-20; see
-# .
+# http://www.mmsp.gov.ma/fr/actualites.aspx?id=288
 
 # From Andrew Paprocki (2013-07-02):
 # Morocco announced that the year's Ramadan daylight-savings
@@ -937,39 +866,36 @@ Zone	Indian/Mayotte	3:00:56 -	LMT	1911 Jul	# Mamoutzou
 # From Sebastien Willemijns (2014-03-18):
 # http://www.afriquinfos.com/articles/2014/3/18/maroc-heure-dete-avancez-tous-horloges-247891.asp
 
-# From Paul Eggert (2014-03-19):
-# To estimate what the Moroccan government will do in future years,
-# transition dates for 2014 through 2038 were determined by running
-# the following program under GNU Emacs 24.3:
-#
-# (let ((islamic-year 1435))
-#   (while (< islamic-year 1461)
-#     (let ((a
-#	     (calendar-gregorian-from-absolute
-#	      (calendar-islamic-to-absolute (list 9 1 islamic-year))))
-#	    (b
-#	     (calendar-gregorian-from-absolute
-#	      (calendar-islamic-to-absolute (list 10 1 islamic-year)))))
-#	(insert
-#	 (format
-#	  (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 3:00\t0\t-\n"
-#		  "Rule\tMorocco\t%d\tonly\t-\t%s\t %2d\t 2:00\t1:00\tS\n")
-#	  (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
-#	  (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
+# From Milamber Space Network (2014-06-05):
+# The Moroccan government has recently announced that the country will return
+# to standard time at 03:00 on Saturday, June 28, 2014 local time....  DST
+# will resume again at 02:00 on Saturday, August 2, 2014....
+# http://www.mmsp.gov.ma/fr/actualites.aspx?id=586
+
+# From Paul Eggert (2014-06-05):
+# For now, guess that later spring and fall transitions will use 2014's rules,
+# and guess that Morocco will switch to standard time at 03:00 the last
+# Saturday before Ramadan, and back to DST at 02:00 the first Saturday after
+# Ramadan.  To implement this, transition dates for 2015 through 2037 were
+# determined by running the following program under GNU Emacs 24.3, with the
+# results integrated by hand into the table below.
+# (let ((islamic-year 1436))
+#   (while (< islamic-year 1460)
+#     (let ((a (calendar-islamic-to-absolute (list 9 1 islamic-year)))
+#           (b (calendar-islamic-to-absolute (list 10 1 islamic-year)))
+#           (saturday 6))
+#       (while (/= saturday (mod (setq a (1- a)) 7)))
+#       (while (/= saturday (mod b 7))
+#         (setq b (1+ b)))
+#       (setq a (calendar-gregorian-from-absolute a))
+#       (setq b (calendar-gregorian-from-absolute b))
+#       (insert
+#        (format
+#         (concat "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 3:00\t0\t-\n"
+#                 "Rule\tMorocco\t%d\tonly\t-\t%s\t%2d\t 2:00\t1:00\tS\n")
+#         (car (cdr (cdr a))) (calendar-month-name (car a) t) (car (cdr a))
+#         (car (cdr (cdr b))) (calendar-month-name (car b) t) (car (cdr b)))))
 #     (setq islamic-year (+ 1 islamic-year))))
-#
-# with spring-forward transitions removed for 2023-2025, when the
-# normal spring-forward date falls during the estimated Ramadan; with
-# all transitions removed for 2026-2035, where the estimated Ramadan
-# falls entirely outside daylight-saving time; and with fall-back
-# transitions removed for 2036-2037, where the normal fall-back
-# date falls during the estimated Ramadan.  Normally, the table would
-# stop after 2037 because 32-bit time_t values roll around early in 2038,
-# but that would imply a prediction of perpetual DST after March 2038
-# due to the year-2037 glitches.  So, this table instead stops after
-# 2038, the first non-glitchy year after the 32-bit rollover.
-# An advantage of stopping after 2038 is that it lets zic guess
-# TZ='WET0WEST,M3.5.0,M10.5.0/3' for time stamps far in the future.
 
 # RULE	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 
@@ -991,46 +917,44 @@ Rule	Morocco	1978	only	-	Aug	 4	 0:00	0	-
 Rule	Morocco	2008	only	-	Jun	 1	 0:00	1:00	S
 Rule	Morocco	2008	only	-	Sep	 1	 0:00	0	-
 Rule	Morocco	2009	only	-	Jun	 1	 0:00	1:00	S
-Rule	Morocco	2009	only	-	Aug	 21	 0:00	0	-
+Rule	Morocco	2009	only	-	Aug	21	 0:00	0	-
 Rule	Morocco	2010	only	-	May	 2	 0:00	1:00	S
 Rule	Morocco	2010	only	-	Aug	 8	 0:00	0	-
 Rule	Morocco	2011	only	-	Apr	 3	 0:00	1:00	S
-Rule	Morocco	2011	only	-	Jul	 31	 0	0	-
-Rule	Morocco	2012	2013	-	Apr	 lastSun 2:00	1:00	S
-Rule	Morocco	2012	only	-	Sep	 30	 3:00	0	-
-Rule	Morocco	2012	only	-	Jul	 20	 3:00	0	-
-Rule	Morocco	2012	only	-	Aug	 20	 2:00	1:00	S
-Rule	Morocco	2013	only	-	Jul	  7	 3:00	0	-
-Rule	Morocco	2013	only	-	Aug	 10	 2:00	1:00	S
-Rule	Morocco	2013	2035	-	Oct	 lastSun 3:00	0	-
-Rule	Morocco	2014	2022	-	Mar	 lastSun 2:00	1:00	S
-Rule	Morocco	2014	only	-	Jun	 29	 3:00	0	-
-Rule	Morocco	2014	only	-	Jul	 29	 2:00	1:00	S
-Rule	Morocco	2015	only	-	Jun	 18	 3:00	0	-
-Rule	Morocco	2015	only	-	Jul	 18	 2:00	1:00	S
-Rule	Morocco	2016	only	-	Jun	  7	 3:00	0	-
-Rule	Morocco	2016	only	-	Jul	  7	 2:00	1:00	S
-Rule	Morocco	2017	only	-	May	 27	 3:00	0	-
-Rule	Morocco	2017	only	-	Jun	 26	 2:00	1:00	S
-Rule	Morocco	2018	only	-	May	 16	 3:00	0	-
-Rule	Morocco	2018	only	-	Jun	 15	 2:00	1:00	S
-Rule	Morocco	2019	only	-	May	  6	 3:00	0	-
-Rule	Morocco	2019	only	-	Jun	  5	 2:00	1:00	S
-Rule	Morocco	2020	only	-	Apr	 24	 3:00	0	-
-Rule	Morocco	2020	only	-	May	 24	 2:00	1:00	S
-Rule	Morocco	2021	only	-	Apr	 13	 3:00	0	-
-Rule	Morocco	2021	only	-	May	 13	 2:00	1:00	S
-Rule	Morocco	2022	only	-	Apr	  3	 3:00	0	-
-Rule	Morocco	2022	only	-	May	  3	 2:00	1:00	S
-Rule	Morocco	2023	only	-	Apr	 22	 2:00	1:00	S
-Rule	Morocco	2024	only	-	Apr	 10	 2:00	1:00	S
-Rule	Morocco	2025	only	-	Mar	 31	 2:00	1:00	S
-Rule	Morocco	2026	max	-	Mar	 lastSun 2:00	1:00	S
-Rule	Morocco	2036	only	-	Oct	 21	 3:00	0	-
-Rule	Morocco	2037	only	-	Oct	 11	 3:00	0	-
-Rule	Morocco	2038	only	-	Sep	 30	 3:00	0	-
-Rule	Morocco	2038	only	-	Oct	 30	 2:00	1:00	S
-Rule	Morocco	2038	max	-	Oct	 lastSun 3:00	0	-
+Rule	Morocco	2011	only	-	Jul	31	 0	0	-
+Rule	Morocco	2012	2013	-	Apr	lastSun	 2:00	1:00	S
+Rule	Morocco	2012	only	-	Sep	30	 3:00	0	-
+Rule	Morocco	2012	only	-	Jul	20	 3:00	0	-
+Rule	Morocco	2012	only	-	Aug	20	 2:00	1:00	S
+Rule	Morocco	2013	only	-	Jul	 7	 3:00	0	-
+Rule	Morocco	2013	only	-	Aug	10	 2:00	1:00	S
+Rule	Morocco	2013	max	-	Oct	lastSun	 3:00	0	-
+Rule	Morocco	2014	2022	-	Mar	lastSun	 2:00	1:00	S
+Rule	Morocco	2014	only	-	Jun	28	 3:00	0	-
+Rule	Morocco	2014	only	-	Aug	 2	 2:00	1:00	S
+Rule	Morocco	2015	only	-	Jun	13	 3:00	0	-
+Rule	Morocco	2015	only	-	Jul	18	 2:00	1:00	S
+Rule	Morocco	2016	only	-	Jun	 4	 3:00	0	-
+Rule	Morocco	2016	only	-	Jul	 9	 2:00	1:00	S
+Rule	Morocco	2017	only	-	May	20	 3:00	0	-
+Rule	Morocco	2017	only	-	Jul	 1	 2:00	1:00	S
+Rule	Morocco	2018	only	-	May	12	 3:00	0	-
+Rule	Morocco	2018	only	-	Jun	16	 2:00	1:00	S
+Rule	Morocco	2019	only	-	May	 4	 3:00	0	-
+Rule	Morocco	2019	only	-	Jun	 8	 2:00	1:00	S
+Rule	Morocco	2020	only	-	Apr	18	 3:00	0	-
+Rule	Morocco	2020	only	-	May	30	 2:00	1:00	S
+Rule	Morocco	2021	only	-	Apr	10	 3:00	0	-
+Rule	Morocco	2021	only	-	May	15	 2:00	1:00	S
+Rule	Morocco	2022	only	-	Apr	 2	 3:00	0	-
+Rule	Morocco	2022	only	-	May	 7	 2:00	1:00	S
+Rule	Morocco	2023	only	-	Apr	22	 2:00	1:00	S
+Rule	Morocco	2024	only	-	Apr	13	 2:00	1:00	S
+Rule	Morocco	2025	only	-	Apr	 5	 2:00	1:00	S
+Rule	Morocco	2026	max	-	Mar	lastSun	 2:00	1:00	S
+Rule	Morocco	2035	only	-	Oct	27	 3:00	0	-
+Rule	Morocco	2036	only	-	Oct	18	 3:00	0	-
+Rule	Morocco	2037	only	-	Oct	10	 3:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Africa/Casablanca	-0:30:20 -	LMT	1913 Oct 26
@@ -1049,11 +973,17 @@ Zone Africa/Casablanca	-0:30:20 -	LMT	1913 Oct 26
 # Assume that this has been true since Western Sahara switched to GMT,
 # since most of it was then controlled by Morocco.
 
-Zone Africa/El_Aaiun	-0:52:48 -	LMT	1934 Jan
+Zone Africa/El_Aaiun	-0:52:48 -	LMT	1934 Jan # El Aaiún
 			-1:00	-	WAT	1976 Apr 14
 			 0:00	Morocco	WE%sT
 
 # Mozambique
+#
+# Shanks gives 1903-03-01 for the transition to CAT.
+# Perhaps the 1911-05-26 Portuguese decree
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# merely made it official?
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Maputo	2:10:20 -	LMT	1903 Mar
 			2:00	-	CAT
@@ -1062,8 +992,8 @@ Zone	Africa/Maputo	2:10:20 -	LMT	1903 Mar
 # The 1994-04-03 transition is from Shanks & Pottenger.
 # Shanks & Pottenger report no DST after 1998-04; go with IATA.
 
-# From Petronella Sibeene (2007-03-30) in
-# :
+# From Petronella Sibeene (2007-03-30):
+# http://allafrica.com/stories/200703300178.html
 # While the entire country changes its time, Katima Mulilo and other
 # settlements in Caprivi unofficially will not because the sun there
 # rises and sets earlier compared to other regions.  Chief of
@@ -1080,34 +1010,41 @@ Rule	Namibia	1994	max	-	Sep	Sun>=1	2:00	1:00	S
 Rule	Namibia	1995	max	-	Apr	Sun>=1	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Windhoek	1:08:24 -	LMT	1892 Feb 8
-			1:30	-	SWAT	1903 Mar	# SW Africa Time
-			2:00	-	SAST	1942 Sep 20 2:00
-			2:00	1:00	SAST	1943 Mar 21 2:00
+			1:30	-	SWAT	1903 Mar    # SW Africa Time
+			2:00	-	SAST	1942 Sep 20  2:00
+			2:00	1:00	SAST	1943 Mar 21  2:00
 			2:00	-	SAST	1990 Mar 21 # independence
 			2:00	-	CAT	1994 Apr  3
 			1:00	Namibia	WA%sT
 
 # Niger
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Niamey	 0:08:28 -	LMT	1912
-			-1:00	-	WAT	1934 Feb 26
-			 0:00	-	GMT	1960
-			 1:00	-	WAT
+# See Africa/Lagos.
 
 # Nigeria
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Lagos	0:13:36 -	LMT	1919 Sep
 			1:00	-	WAT
+Link Africa/Lagos Africa/Bangui	     # Central African Republic
+Link Africa/Lagos Africa/Brazzaville # Rep. of the Congo
+Link Africa/Lagos Africa/Douala	     # Cameroon
+Link Africa/Lagos Africa/Kinshasa    # Dem. Rep. of the Congo (west)
+Link Africa/Lagos Africa/Libreville  # Gabon
+Link Africa/Lagos Africa/Luanda	     # Angola
+Link Africa/Lagos Africa/Malabo	     # Equatorial Guinea
+Link Africa/Lagos Africa/Niamey	     # Niger
+Link Africa/Lagos Africa/Porto-Novo  # Benin
 
-# Reunion
+# Réunion
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Reunion	3:41:52 -	LMT	1911 Jun	# Saint-Denis
-			4:00	-	RET	# Reunion Time
+Zone	Indian/Reunion	3:41:52 -	LMT	1911 Jun # Saint-Denis
+			4:00	-	RET	# Réunion Time
 #
-# Scattered Islands (Iles Eparses) administered from Reunion are as follows.
+# Crozet Islands also observes Réunion time; see the 'antarctica' file.
+#
+# Scattered Islands (Îles Éparses) administered from Réunion are as follows.
 # The following information about them is taken from
-# Iles Eparses (www.outre-mer.gouv.fr/domtom/ile.htm, 1997-07-22, in French;
-# no longer available as of 1999-08-17).
+# Îles Éparses (, 1997-07-22,
+# in French; no longer available as of 1999-08-17).
 # We have no info about their time zone histories.
 #
 # Bassas da India - uninhabited
@@ -1122,32 +1059,21 @@ Zone	Africa/Kigali	2:00:16 -	LMT	1935 Jun
 			2:00	-	CAT
 
 # St Helena
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/St_Helena	-0:22:48 -	LMT	1890		# Jamestown
-			-0:22:48 -	JMT	1951	# Jamestown Mean Time
-			 0:00	-	GMT
+# See Africa/Abidjan.
 # The other parts of the St Helena territory are similar:
 #	Tristan da Cunha: on GMT, say Whitman and the CIA
-#	Ascension: on GMT, says usno1995 and the CIA
+#	Ascension: on GMT, say the USNO (1995-12-21) and the CIA
 #	Gough (scientific station since 1955; sealers wintered previously):
 #		on GMT, says the CIA
-#	Inaccessible, Nightingale: no information, but probably GMT
-
-# Sao Tome and Principe
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Sao_Tome	 0:26:56 -	LMT	1884
-			-0:36:32 -	LMT	1912	# Lisbon Mean Time
-			 0:00	-	GMT
+#	Inaccessible, Nightingale: uninhabited
 
+# São Tomé and Príncipe
 # Senegal
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Dakar	-1:09:44 -	LMT	1912
-			-1:00	-	WAT	1941 Jun
-			 0:00	-	GMT
+# See Africa/Abidjan.
 
 # Seychelles
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun	# Victoria
+Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun # Victoria
 			4:00	-	SCT	# Seychelles Time
 # From Paul Eggert (2001-05-30):
 # Aldabra, Farquhar, and Desroches, originally dependencies of the
@@ -1157,17 +1083,7 @@ Zone	Indian/Mahe	3:41:48 -	LMT	1906 Jun	# Victoria
 # Possibly the islands were uninhabited.
 
 # Sierra Leone
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Whitman gives Mar 31 - Aug 31 for 1931 on; go with Shanks & Pottenger.
-Rule	SL	1935	1942	-	Jun	 1	0:00	0:40	SLST
-Rule	SL	1935	1942	-	Oct	 1	0:00	0	WAT
-Rule	SL	1957	1962	-	Jun	 1	0:00	1:00	SLST
-Rule	SL	1957	1962	-	Sep	 1	0:00	0	GMT
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Freetown	-0:53:00 -	LMT	1882
-			-0:53:00 -	FMT	1913 Jun # Freetown Mean Time
-			-1:00	SL	%s	1957
-			 0:00	SL	%s
+# See Africa/Abidjan.
 
 # Somalia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -1190,9 +1106,9 @@ Zone Africa/Johannesburg 1:52:00 -	LMT	1892 Feb 8
 
 # Sudan
 #
-# From 
-# Sudan News Agency (2000-01-13)
-# , also reported by Michael De Beukelaer-Dossche via Steffen Thorsen:
+# From 
+# Sudan News Agency (2000-01-13),
+# also reported by Michaël De Beukelaer-Dossche via Steffen Thorsen:
 # Clocks will be moved ahead for 60 minutes all over the Sudan as of noon
 # Saturday....  This was announced Thursday by Caretaker State Minister for
 # Manpower Abdul-Rahman Nur-Eddin.
@@ -1223,14 +1139,12 @@ Zone Africa/Dar_es_Salaam 2:37:08 -	LMT	1931
 			3:00	-	EAT
 
 # Togo
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Africa/Lome	0:04:52 -	LMT	1893
-			0:00	-	GMT
+# See Africa/Abidjan.
 
 # Tunisia
 
 # From Gwillim Law (2005-04-30):
-# My correspondent, Risto Nykanen, has alerted me to another adoption of DST,
+# My correspondent, Risto Nykänen, has alerted me to another adoption of DST,
 # this time in Tunisia.  According to Yahoo France News
 # , in a story attributed to AP
 # and dated 2005-04-26, "Tunisia has decided to advance its official time by
@@ -1239,8 +1153,8 @@ Zone	Africa/Lome	0:04:52 -	LMT	1893
 # Saturday."  (My translation)
 #
 # From Oscar van Vlijmen (2005-05-02):
-# LaPresse, the first national daily newspaper ...
-# 
+# La Presse, the first national daily newspaper ...
+# http://www.lapresse.tn/archives/archives280405/actualites/lheure.html
 # ... DST for 2005: on: Sun May 1 0h standard time, off: Fri Sept. 30,
 # 1h standard time.
 #
@@ -1253,18 +1167,12 @@ Zone	Africa/Lome	0:04:52 -	LMT	1893
 # From Steffen Thorsen (2009-03-16):
 # According to several news sources, Tunisia will not observe DST this year.
 # (Arabic)
-# 
 # http://www.elbashayer.com/?page=viewn&nid=42546
-# 
-# 
 # http://www.babnet.net/kiwidetail-15295.asp
-# 
 #
 # We have also confirmed this with the US embassy in Tunisia.
 # We have a wrap-up about this on the following page:
-# 
 # http://www.timeanddate.com/news/time/tunisia-cancels-dst-2009.html
-# 
 
 # From Alexander Krivenyshev (2009-03-17):
 # Here is a link to Tunis Afrique Presse News Agency
@@ -1272,20 +1180,17 @@ Zone	Africa/Lome	0:04:52 -	LMT	1893
 # Standard time to be kept the whole year long (tap.info.tn):
 #
 # (in English)
-# 
 # http://www.tap.info.tn/en/index.php?option=com_content&task=view&id=26813&Itemid=157
-# 
 #
 # (in Arabic)
-# 
 # http://www.tap.info.tn/ar/index.php?option=com_content&task=view&id=61240&Itemid=1
-# 
 
-# From Arthur David Olson (2009--3-18):
-# The Tunis Afrique Presse News Agency notice contains this: "This measure is due to the fact
-# that the fasting month of ramadan coincides with the period concerned by summer time.
-# Therefore, the standard time will be kept unchanged the whole year long."
-# So foregoing DST seems to be an exception (albeit one that may be repeated in the  future).
+# From Arthur David Olson (2009-03-18):
+# The Tunis Afrique Presse News Agency notice contains this: "This measure is
+# due to the fact that the fasting month of Ramadan coincides with the period
+# concerned by summer time.  Therefore, the standard time will be kept
+# unchanged the whole year long."  So foregoing DST seems to be an exception
+# (albeit one that may be repeated in the future).
 
 # From Alexander Krivenyshev (2010-03-27):
 # According to some news reports Tunis confirmed not to use DST in 2010
@@ -1297,12 +1202,8 @@ Zone	Africa/Lome	0:04:52 -	LMT	1893
 # coincided with the month of Ramadan..."
 #
 # (in Arabic)
-# 
 # http://www.moheet.com/show_news.aspx?nid=358861&pg=1
-# 
 # http://www.almadenahnews.com/newss/news.php?c=118&id=38036
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_tunis02.html
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -1337,7 +1238,7 @@ Rule	Tunisia	2006	2008	-	Oct	lastSun	 2:00s	0	-
 # Shanks & Pottenger say the 1911 switch was on Mar 9; go with Howse's Mar 11.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Africa/Tunis	0:40:44 -	LMT	1881 May 12
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
 			1:00	Tunisia	CE%sT
 
 # Uganda
diff --git a/jdk/make/data/tzdata/antarctica b/jdk/make/data/tzdata/antarctica
index e31bada94fb..0cdac270861 100644
--- a/jdk/make/data/tzdata/antarctica
+++ b/jdk/make/data/tzdata/antarctica
@@ -21,19 +21,16 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # From Paul Eggert (1999-11-15):
 # To keep things manageable, we list only locations occupied year-round; see
-# 
 # COMNAP - Stations and Bases
-# 
+# http://www.comnap.aq/comnap/comnap.nsf/P/Stations/
 # and
-# 
 # Summary of the Peri-Antarctic Islands (1998-07-23)
-# 
+# http://www.spri.cam.ac.uk/bob/periant.htm
 # for information.
 # Unless otherwise specified, we have no time zone information.
 #
@@ -78,19 +75,19 @@ Rule	ChileAQ	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
 
 # Argentina - year-round bases
 # Belgrano II, Confin Coast, -770227-0343737, since 1972-02-05
-# Esperanza, San Martin Land, -6323-05659, since 1952-12-17
-# Jubany, Potter Peninsula, King George Island, -6414-0602320, since 1982-01
-# Marambio, Seymour I, -6414-05637, since 1969-10-29
+# Carlini, Potter Cove, King George Island, -6414-0602320, since 1982-01
+# Esperanza, Hope Bay, -6323-05659, since 1952-12-17
+# Marambio, -6414-05637, since 1969-10-29
 # Orcadas, Laurie I, -6016-04444, since 1904-02-22
-# San Martin, Debenham I, -6807-06708, since 1951-03-21
+# San Martín, Barry I, -6808-06706, since 1951-03-21
 #	(except 1960-03 / 1976-03-21)
 
 # Australia - territories
 # Heard Island, McDonald Islands (uninhabited)
 #	previously sealers and scientific personnel wintered
-#	
 #	Margaret Turner reports
-#	 (1999-09-30) that they're UTC+5, with no DST;
+#	http://web.archive.org/web/20021204222245/http://www.dstc.qut.edu.au/DST/marg/daylight.html
+#	(1999-09-30) that they're UTC+5, with no DST;
 #	presumably this is when they have visitors.
 #
 # year-round bases
@@ -107,14 +104,10 @@ Rule	ChileAQ	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
 # The changes occurred on 2009-10-18 at 02:00 (local times).
 #
 # Government source: (Australian Antarctic Division)
-# 
 # http://www.aad.gov.au/default.asp?casid=37079
-# 
 #
 # We have more background information here:
-# 
 # http://www.timeanddate.com/news/time/antarctica-new-times.html
-# 
 
 # From Steffen Thorsen (2010-03-10):
 # We got these changes from the Australian Antarctic Division: ...
@@ -129,50 +122,49 @@ Rule	ChileAQ	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
 # - Mawson station stays on UTC+5.
 #
 # Background:
-# 
 # http://www.timeanddate.com/news/time/antartica-time-changes-2010.html
-# 
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Casey	0	-	zzz	1969
-			8:00	-	WST	2009 Oct 18 2:00
-						# Western (Aus) Standard Time
-			11:00	-	CAST	2010 Mar 5 2:00
-						# Casey Time
-			8:00	-	WST	2011 Oct 28 2:00
+			8:00	-	AWST	2009 Oct 18  2:00
+						# Australian Western Std Time
+			11:00	-	CAST	2010 Mar  5  2:00  # Casey Time
+			8:00	-	AWST	2011 Oct 28  2:00
 			11:00	-	CAST	2012 Feb 21 17:00u
-			8:00	-	WST
+			8:00	-	AWST
 Zone Antarctica/Davis	0	-	zzz	1957 Jan 13
-			7:00	-	DAVT	1964 Nov # Davis Time
+			7:00	-	DAVT	1964 Nov    # Davis Time
 			0	-	zzz	1969 Feb
-			7:00	-	DAVT	2009 Oct 18 2:00
+			7:00	-	DAVT	2009 Oct 18  2:00
 			5:00	-	DAVT	2010 Mar 10 20:00u
-			7:00	-	DAVT	2011 Oct 28 2:00
+			7:00	-	DAVT	2011 Oct 28  2:00
 			5:00	-	DAVT	2012 Feb 21 20:00u
 			7:00	-	DAVT
 Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
-			6:00	-	MAWT	2009 Oct 18 2:00
-						# Mawson Time
+			6:00	-	MAWT	2009 Oct 18  2:00 # Mawson Time
 			5:00	-	MAWT
 # References:
-# 
 # Casey Weather (1998-02-26)
-# 
-# 
+# http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html
 # Davis Station, Antarctica (1998-02-26)
-# 
-# 
+# http://www.antdiv.gov.au/aad/exop/sfo/davis/video.html
 # Mawson Station, Antarctica (1998-02-25)
-# 
+# http://www.antdiv.gov.au/aad/exop/sfo/mawson/video.html
+
+# Belgium - year-round base
+# Princess Elisabeth, Queen Maud Land, -713412+0231200, since 2007
 
 # Brazil - year-round base
-# Comandante Ferraz, King George Island, -6205+05824, since 1983/4
+# Ferraz, King George Island, -6205+05824, since 1983/4
+
+# Bulgaria - year-round base
+# St. Kliment Ohridski, Livingston Island, -623829-0602153, since 1988
 
 # Chile - year-round bases and towns
 # Escudero, South Shetland Is, -621157-0585735, since 1994
-# Presidente Eduadro Frei, King George Island, -6214-05848, since 1969-03-07
-# General Bernardo O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
-# Capitan Arturo Prat, -6230-05941
+# Frei Montalva, King George Island, -6214-05848, since 1969-03-07
+# O'Higgins, Antarctic Peninsula, -6319-05704, since 1948-02
+# Prat, -6230-05941
 # Villa Las Estrellas (a town), around the Frei base, since 1984-04-09
 # These locations have always used Santiago time; use TZ='America/Santiago'.
 
@@ -180,31 +172,35 @@ Zone Antarctica/Mawson	0	-	zzz	1954 Feb 13
 # Great Wall, King George Island, -6213-05858, since 1985-02-20
 # Zhongshan, Larsemann Hills, Prydz Bay, -6922+07623, since 1989-02-26
 
-# France - year-round bases
+# France - year-round bases (also see "France & Italy")
 #
 # From Antoine Leca (1997-01-20):
-# Time data are from Nicole Pailleau at the IFRTP
+# Time data entries are from Nicole Pailleau at the IFRTP
 # (French Institute for Polar Research and Technology).
-# She confirms that French Southern Territories and Terre Adelie bases
-# don't observe daylight saving time, even if Terre Adelie supplies came
+# She confirms that French Southern Territories and Terre Adélie bases
+# don't observe daylight saving time, even if Terre Adélie supplies came
 # from Tasmania.
 #
 # French Southern Territories with year-round inhabitants
 #
-# Martin-de-Vivies Base, Amsterdam Island, -374105+0773155, since 1950
-# Alfred-Faure Base, Crozet Islands, -462551+0515152, since 1964
-# Port-aux-Francais, Kerguelen Islands, -492110+0701303, since 1951;
+# Alfred Faure, Possession Island, Crozet Islands, -462551+0515152, since 1964;
+#	sealing & whaling stations operated variously 1802/1911+;
+#	see Indian/Reunion.
+#
+# Martin-de-Viviès, Amsterdam Island, -374105+0773155, since 1950
+# Port-aux-Français, Kerguelen Islands, -492110+0701303, since 1951;
 #	whaling & sealing station operated 1908/1914, 1920/1929, and 1951/1956
 #
 # St Paul Island - near Amsterdam, uninhabited
 #	fishing stations operated variously 1819/1931
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Indian/Kerguelen	0	-	zzz	1950	# Port-aux-Francais
+Zone Indian/Kerguelen	0	-	zzz	1950 # Port-aux-Français
 			5:00	-	TFT	# ISO code TF Time
 #
 # year-round base in the main continent
-# Dumont-d'Urville, Ile des Petrels, -6640+14001, since 1956-11
+# Dumont d'Urville, Île des Pétrels, -6640+14001, since 1956-11
+#  (2005-12-05)
 #
 # Another base at Port-Martin, 50km east, began operation in 1947.
 # It was destroyed by fire on 1952-01-14.
@@ -214,20 +210,22 @@ Zone Antarctica/DumontDUrville 0 -	zzz	1947
 			10:00	-	PMT	1952 Jan 14 # Port-Martin Time
 			0	-	zzz	1956 Nov
 			10:00	-	DDUT	# Dumont-d'Urville Time
-# Reference:
-# 
-# Dumont d'Urville Station (2005-12-05)
-# 
+
+# France & Italy - year-round base
+# Concordia, -750600+1232000, since 2005
 
 # Germany - year-round base
-# Georg von Neumayer, -7039-00815
+# Neumayer III, -704080-0081602, since 2009
 
-# India - year-round base
-# Dakshin Gangotri, -7005+01200
+# India - year-round bases
+# Bharati, -692428+0761114, since 2012
+# Maitri, -704558+0114356, since 1989
+
+# Italy - year-round base (also see "France & Italy")
+# Zuchelli, Terra Nova Bay, -744140+1640647, since 1986
 
 # Japan - year-round bases
-# Dome Fuji, -7719+03942
-# Syowa, -690022+0393524
+# Syowa (also known as Showa), -690022+0393524, since 1957
 #
 # From Hideyuki Suzuki (1999-02-06):
 # In all Japanese stations, +0300 is used as the standard time.
@@ -239,11 +237,11 @@ Zone Antarctica/DumontDUrville 0 -	zzz	1947
 Zone Antarctica/Syowa	0	-	zzz	1957 Jan 29
 			3:00	-	SYOT	# Syowa Time
 # See:
-# 
 # NIPR Antarctic Research Activities (1999-08-17)
-# 
+# http://www.nipr.ac.jp/english/ara01.html
 
 # S Korea - year-round base
+# Jang Bogo, Terra Nova Bay, -743700+1641205 since 2014
 # King Sejong, King George Island, -6213-05847, since 1988
 
 # New Zealand - claims
@@ -287,11 +285,14 @@ Rule	Troll	2005	max	-	Mar	lastSun	1:00u	2:00	CEST
 Rule	Troll	2004	max	-	Oct	lastSun	1:00u	0:00	UTC
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
-     			0:00	Troll	%s
+			0:00	Troll	%s
 
 # Poland - year-round base
 # Arctowski, King George Island, -620945-0582745, since 1977
 
+# Romania - year-bound base
+# Law-Racoviță, Larsemann Hills, -692319+0762251, since 1986
+
 # Russia - year-round bases
 # Bellingshausen, King George Island, -621159-0585337, since 1968-02-22
 # Mirny, Davis coast, -6633+09301, since 1956-02
@@ -301,8 +302,8 @@ Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
 #	year-round from 1960/61 to 1992
 
 # Vostok, since 1957-12-16, temporarily closed 1994-02/1994-11
-# 
-# From Craig Mundell (1994-12-15):
+# From Craig Mundell (1994-12-15):
+# http://quest.arc.nasa.gov/antarctica/QA/computers/Directions,Time,ZIP
 # Vostok, which is one of the Russian stations, is set on the same
 # time as Moscow, Russia.
 #
@@ -317,7 +318,7 @@ Zone Antarctica/Troll	0	-	zzz	2005 Feb 12
 #
 # From Paul Eggert (2001-05-04):
 # This seems to be hopelessly confusing, so I asked Lee Hotz about it
-# in person.  He said that some Antartic locations set their local
+# in person.  He said that some Antarctic locations set their local
 # time so that noon is the warmest part of the day, and that this
 # changes during the year and does not necessarily correspond to mean
 # solar noon.  So the Vostok time might have been whatever the clocks
@@ -329,9 +330,12 @@ Zone Antarctica/Vostok	0	-	zzz	1957 Dec 16
 
 # S Africa - year-round bases
 # Marion Island, -4653+03752
-# Sanae, -7141-00250
+# SANAE IV, Vesleskarvet, Queen Maud Land, -714022-0025026, since 1997
 
-# UK
+# Ukraine - year-round base
+# Vernadsky (formerly Faraday), Galindez Island, -651445-0641526, since 1954
+
+# United Kingdom
 #
 # British Antarctic Territories (BAT) claims
 # South Orkney Islands
@@ -387,7 +391,7 @@ Zone Antarctica/Palmer	0	-	zzz	1965
 # but that he found it more convenient to keep GMT+12
 # as supplies for the station were coming from McMurdo Sound,
 # which was on GMT+12 because New Zealand was on GMT+12 all year
-# at that time (1957).  (Source: Siple's book 90 degrees SOUTH.)
+# at that time (1957).  (Source: Siple's book 90 Degrees South.)
 #
 # From Susan Smith
 # http://www.cybertours.com/whs/pole10.html
diff --git a/jdk/make/data/tzdata/asia b/jdk/make/data/tzdata/asia
index 595c8ed7245..906c0a97cda 100644
--- a/jdk/make/data/tzdata/asia
+++ b/jdk/make/data/tzdata/asia
@@ -21,13 +21,13 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-08-11):
 #
@@ -49,13 +49,17 @@
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# .
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
+#
+# For Russian data circa 1919, a source is:
+# Byalokoz EL. New Counting of Time in Russia since July 1, 1919.
+# (See the 'europe' file for a fuller citation.)
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
-# I invented the abbreviations marked `*' in the following table;
+# I invented the abbreviations marked '*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
 # Corrections are welcome!
 #	     std  dst
@@ -70,13 +74,14 @@
 #	7:00 WIB	west Indonesia (Waktu Indonesia Barat)
 #	8:00 WITA	central Indonesia (Waktu Indonesia Tengah)
 #	8:00 CST	China
-#	9:00 CJT	Central Japanese Time (1896/1937)*
+#	8:00 JWST	Western Standard Time (Japan, 1896/1937)*
+#	9:00 JCST	Central Standard Time (Japan, 1896/1937)
 #	9:00 WIT	east Indonesia (Waktu Indonesia Timur)
 #	9:00 JST  JDT	Japan
 #	9:00 KST  KDT	Korea
-#	9:30 CST	(Australian) Central Standard Time
+#	9:30 ACST	Australian Central Standard Time
 #
-# See the `europe' file for Russia and Turkey in Asia.
+# See the 'europe' file for Russia and Turkey in Asia.
 
 # From Guy Harris:
 # Incorporates data for Singapore from Robert Elz' asia 1.1, as well as
@@ -86,7 +91,7 @@
 
 ###############################################################################
 
-# These rules are stolen from the `europe' file.
+# These rules are stolen from the 'europe' file.
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	EUAsia	1981	max	-	Mar	lastSun	 1:00u	1:00	S
 Rule	EUAsia	1979	1995	-	Sep	lastSun	 1:00u	0	-
@@ -138,11 +143,11 @@ Zone	Asia/Kabul	4:36:48 -	LMT	1890
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Yerevan	2:58:00 -	LMT	1924 May  2
 			3:00	-	YERT	1957 Mar    # Yerevan Time
-			4:00 RussiaAsia YER%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia YER%sT	1991 Mar 31  2:00s
 			3:00	1:00	YERST	1991 Sep 23 # independence
-			3:00 RussiaAsia	AM%sT	1995 Sep 24 2:00s
+			3:00 RussiaAsia	AM%sT	1995 Sep 24  2:00s
 			4:00	-	AMT	1997
-			4:00 RussiaAsia	AM%sT	2012 Mar 25 2:00s
+			4:00 RussiaAsia	AM%sT	2012 Mar 25  2:00s
 			4:00	-	AMT
 
 # Azerbaijan
@@ -155,16 +160,16 @@ Rule	Azer	1997	max	-	Oct	lastSun	 5:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Baku	3:19:24 -	LMT	1924 May  2
 			3:00	-	BAKT	1957 Mar    # Baku Time
-			4:00 RussiaAsia BAK%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia BAK%sT	1991 Mar 31  2:00s
 			3:00	1:00	BAKST	1991 Aug 30 # independence
 			3:00 RussiaAsia	AZ%sT	1992 Sep lastSat 23:00
-			4:00	-	AZT	1996 # Azerbaijan time
+			4:00	-	AZT	1996     # Azerbaijan Time
 			4:00	EUAsia	AZ%sT	1997
 			4:00	Azer	AZ%sT
 
 # Bahrain
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
+Zone	Asia/Bahrain	3:22:20 -	LMT	1920     # Manamah
 			4:00	-	GST	1972 Jun
 			3:00	-	AST
 
@@ -174,13 +179,8 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 # Daylight Saving Time from June 16 to Sept 30
 #
 # Bangladesh to introduce daylight saving time likely from June 16
-# 
 # http://www.asiantribune.com/?q=node/17288
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh02.html
-# 
 #
 # "... Bangladesh government has decided to switch daylight saving time from
 # June
@@ -195,17 +195,11 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 # the 19th and 20th, and they have not set the end date yet.
 #
 # Some sources:
-# 
 # http://in.reuters.com/article/southAsiaNews/idINIndia-40017620090601
-# 
-# 
 # http://bdnews24.com/details.php?id=85889&cid=2
-# 
 #
 # Our wrap-up:
-# 
 # http://www.timeanddate.com/news/time/bangladesh-daylight-saving-2009.html
-# 
 
 # From A. N. M. Kamrus Saadat (2009-06-15):
 # Finally we've got the official mail regarding DST start time where DST start
@@ -220,13 +214,8 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 #
 # Following report by same newspaper-"The Daily Star Friday":
 # "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1"
-# 
 # http://www.thedailystar.net/newDesign/news-details.php?nid=107021
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html
-# 
 
 # From Steffen Thorsen (2009-10-13):
 # IANS (Indo-Asian News Service) now reports:
@@ -235,22 +224,15 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 # "continue for an indefinite period."
 #
 # One of many places where it is published:
-# 
 # http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html
-# 
 
 # From Alexander Krivenyshev (2009-12-24):
 # According to Bangladesh newspaper "The Daily Star,"
 # Bangladesh will change its clock back to Standard Time on Dec 31, 2009.
 #
 # Clock goes back 1-hr on Dec 31 night.
-# 
 # http://www.thedailystar.net/newDesign/news-details.php?nid=119228
-# 
-# and
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh05.html
-# 
 #
 # "...The government yesterday decided to put the clock back by one hour
 # on December 31 midnight and the new time will continue until March 31,
@@ -260,17 +242,12 @@ Zone	Asia/Bahrain	3:22:20 -	LMT	1920		# Al Manamah
 # From Alexander Krivenyshev (2010-03-22):
 # According to Bangladesh newspaper "The Daily Star,"
 # Cabinet cancels Daylight Saving Time
-# 
 # http://www.thedailystar.net/newDesign/latest_news.php?nid=22817
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_bangladesh06.html
-# 
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Dhaka	2009	only	-	Jun	19	23:00	1:00	S
-Rule	Dhaka	2009	only	-	Dec	31	23:59	0	-
+Rule	Dhaka	2009	only	-	Dec	31	24:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dhaka	6:01:40 -	LMT	1890
@@ -301,7 +278,7 @@ Zone	Indian/Chagos	4:49:40	-	LMT	1907
 
 # Brunei
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar   # Bandar Seri Begawan
+Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar # Bandar Seri Begawan
 			7:30	-	BNT	1933
 			8:00	-	BNT
 
@@ -310,16 +287,16 @@ Zone	Asia/Brunei	7:39:40 -	LMT	1926 Mar   # Bandar Seri Begawan
 # Milne says 6:24:40 was the meridian of the time ball observatory at Rangoon.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Rangoon	6:24:40 -	LMT	1880		# or Yangon
-			6:24:40	-	RMT	1920	   # Rangoon Mean Time?
-			6:30	-	BURT	1942 May   # Burma Time
-			9:00	-	JST	1945 May 3
-			6:30	-	MMT		   # Myanmar Time
+Zone	Asia/Rangoon	6:24:40 -	LMT	1880        # or Yangon
+			6:24:40	-	RMT	1920        # Rangoon Mean Time?
+			6:30	-	BURT	1942 May    # Burma Time
+			9:00	-	JST	1945 May  3
+			6:30	-	MMT	# Myanmar Time
 
 # Cambodia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
@@ -332,12 +309,12 @@ Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
 # From Bob Devine (1988-01-28):
 # No they don't.  See TIME mag, 1986-02-17 p.52.  Even though
 # China is across 4 physical time zones, before Feb 1, 1986 only the
-# Peking (Bejing) time zone was recognized.  Since that date, China
-# has two of 'em -- Peking's and Urumqi (named after the capital of
+# Peking (Beijing) time zone was recognized.  Since that date, China
+# has two of 'em - Peking's and Ürümqi (named after the capital of
 # the Xinjiang Uyghur Autonomous Region).  I don't know about DST for it.
 #
 # . . .I just deleted the DST table and this editor makes it too
-# painful to suck in another copy..  So, here is what I have for
+# painful to suck in another copy.  So, here is what I have for
 # DST start/end dates for Peking's time zone (info from AP):
 #
 #     1986 May 4 - Sept 14
@@ -347,15 +324,16 @@ Zone	Asia/Phnom_Penh	6:59:40 -	LMT	1906 Jun  9
 # CHINA               8 H  AHEAD OF UTC  ALL OF CHINA, INCL TAIWAN
 # CHINA               9 H  AHEAD OF UTC  APR 17 - SEP 10
 
-# From Paul Eggert (2006-03-22):
-# Shanks & Pottenger write that China (except for Hong Kong and Macau)
-# has had a single time zone since 1980 May 1, observing summer DST
-# from 1986 through 1991; this contradicts Devine's
-# note about Time magazine, though apparently _something_ happened in 1986.
-# Go with Shanks & Pottenger for now.  I made up names for the other
-# pre-1980 time zones.
+# From Paul Eggert (2008-02-11):
+# Jim Mann, "A clumsy embrace for another western custom: China on daylight
+# time - sort of", Los Angeles Times, 1986-05-05 ... [says] that China began
+# observing daylight saving time in 1986.
 
-# From Shanks & Pottenger:
+# From Paul Eggert (2014-06-30):
+# Shanks & Pottenger have China switching to a single time zone in 1980, but
+# this doesn't seem to be correct.  They also write that China observed summer
+# DST from 1986 through 1991, which seems to match the above commentary, so
+# go with them for DST rules as follows:
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Shang	1940	only	-	Jun	 3	0:00	1:00	D
 Rule	Shang	1940	1941	-	Oct	 1	0:00	0	S
@@ -369,7 +347,7 @@ Rule	PRC	1987	1991	-	Apr	Sun>=10	0:00	1:00	D
 # historic timezones from some Taiwan websites.  And yes, there are official
 # Chinese names for these locales (before 1949).
 #
-# From Jesper Norgaard Welen (2006-07-14):
+# From Jesper Nørgaard Welen (2006-07-14):
 # I have investigated the timezones around 1970 on the
 # http://www.astro.com/atlas site [with provinces and county
 # boundaries summarized below]....  A few other exceptions were two
@@ -380,65 +358,97 @@ Rule	PRC	1987	1991	-	Apr	Sun>=10	0:00	1:00	D
 # (could be true), for the moment I am assuming that those two
 # counties are mistakes in the astro.com data.
 
-# From Paul Eggert (2008-02-11):
-# I just now checked Google News for western news sources that talk
-# about China's single time zone, and couldn't find anything before 1986
-# talking about China being in one time zone.  (That article was: Jim
-# Mann, "A clumsy embrace for another western custom: China on daylight
-# time--sort of", Los Angeles Times, 1986-05-05.  By the way, this
-# article confirms the tz database's data claiming that China began
-# observing daylight saving time in 1986.
+# From Paul Eggert (2014-06-30):
+# Alois Treindl kindly sent me translations of the following two sources:
 #
-# From Thomas S. Mullaney (2008-02-11):
-# I think you're combining two subjects that need to treated
-# separately: daylight savings (which, you're correct, wasn't
-# implemented until the 1980s) and the unified time zone centered near
-# Beijing (which was implemented in 1949). Briefly, there was also a
-# "Lhasa Time" in Tibet and "Urumqi Time" in Xinjiang. The first was
-# ceased, and the second eventually recognized (again, in the 1980s).
+# (1)
+# Guo Qingsheng (National Time-Service Center, CAS, Xi'an 710600, China)
+# Beijing Time at the Beginning of the PRC
+# China Historical Materials of Science and Technology
+# (Zhongguo ke ji shi liao, 中国科技史料), Vol. 24, No. 1 (2003)
+# It gives evidence that at the beginning of the PRC, Beijing time was
+# officially apparent solar time!  However, Guo also says that the
+# evidence is dubious, as the relevant institute of astronomy had not
+# been taken over by the PRC yet.  It's plausible that apparent solar
+# time was announced but never implemented, and that people continued
+# to use UT+8.  As the Shanghai radio station (and I presume the
+# observatory) was still under control of French missionaries, it
+# could well have ignored any such mandate.
 #
-# From Paul Eggert (2008-06-30):
-# There seems to be a good chance China switched to a single time zone in 1949
-# rather than in 1980 as Shanks & Pottenger have it, but we don't have a
-# reliable documentary source saying so yet, so for now we still go with
-# Shanks & Pottenger.
-
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Changbai Time ("Long-white Time", Long-white = Heilongjiang area)
+# (2)
+# Guo Qing-sheng (Shaanxi Astronomical Observatory, CAS, Xi'an 710600, China)
+# A Study on the Standard Time Changes for the Past 100 Years in China
+# [undated and unknown publication location]
+# It says several things:
+#   * The Qing dynasty used local apparent solar time throughout China.
+#   * The Republic of China instituted Beijing mean solar time effective
+#     the official calendar book of 1914.
+#   * The French Concession in Shanghai set up signal stations in
+#     French docks in the 1890s, controlled by Xujiahui (Zikawei)
+#     Observatory and set to local mean time.
+#   * "From the end of the 19th century" it changed to UT+8.
+#   * Chinese Customs (by then reduced to a tool of foreign powers)
+#     eventually standardized on this time for all ports, and it
+#     became used by railways as well.
+#   * In 1918 the Central Observatory proposed dividing China into
+#     five time zones (see below for details).  This caught on
+#     at first only in coastal areas observing UT+8.
+#   * During WWII all of China was in theory was at UT+7.  In practice
+#     this was ignored in the west, and I presume was ignored in
+#     Japanese-occupied territory.
+#   * Japanese-occupied Manchuria was at UT+9, i.e., Japan time.
+#   * The five-zone plan was resurrected after WWII and officially put into
+#     place (with some modifications) in March 1948.  It's not clear
+#     how well it was observed in areas under Nationalist control.
+#   * The People's Liberation Army used UT+8 during the civil war.
+#
+# An AP article "Shanghai Internat'l Area Little Changed" in the
+# Lewiston (ME) Daily Sun (1939-05-29), p 17, said "Even the time is
+# different - the occupied districts going by Tokyo time, an hour
+# ahead of that prevailing in the rest of Shanghai."  Guess that the
+# Xujiahui Observatory was under French control and stuck with UT+8.
+#
+# In earlier versions of this file, China had many separate Zone entries, but
+# this was based on what were apparently incorrect data in Shanks & Pottenger.
+# This has now been simplified to the two entries Asia/Shanghai and
+# Asia/Urumqi, with the others being links for backward compatibility.
+# Proposed in 1918 and theoretically in effect until 1949 (although in practice
+# mainly observed in coastal areas), the five zones were:
+#
+# Changbai Time ("Long-white Time", Long-white = Heilongjiang area) UT+8.5
+# Asia/Harbin (currently a link to Asia/Shanghai)
 # Heilongjiang (except Mohe county), Jilin
-Zone	Asia/Harbin	8:26:44	-	LMT	1928 # or Haerbin
-			8:30	-	CHAT	1932 Mar # Changbai Time
-			8:00	-	CST	1940
-			9:00	-	CHAT	1966 May
-			8:30	-	CHAT	1980 May
-			8:00	PRC	C%sT
-# Zhongyuan Time ("Central plain Time")
+#
+# Zhongyuan Time ("Central plain Time") UT+8
+# Asia/Shanghai
 # most of China
-# Milne gives 8:05:56.7; round to nearest.
-Zone	Asia/Shanghai	8:05:57	-	LMT	1928
-			8:00	Shang	C%sT	1949
-			8:00	PRC	C%sT
-# Long-shu Time (probably due to Long and Shu being two names of that area)
+# This currently represents most other zones as well,
+# as apparently these regions have been the same since 1970.
+# Milne gives 8:05:43.2 for Xujiahui Observatory time; round to nearest.
+# Guo says Shanghai switched to UT+8 "from the end of the 19th century".
+#
+# Long-shu Time (probably due to Long and Shu being two names of that area) UT+7
+# Asia/Chongqing (currently a link to Asia/Shanghai)
 # Guangxi, Guizhou, Hainan, Ningxia, Sichuan, Shaanxi, and Yunnan;
 # most of Gansu; west Inner Mongolia; west Qinghai; and the Guangdong
 # counties Deqing, Enping, Kaiping, Luoding, Taishan, Xinxing,
 # Yangchun, Yangjiang, Yu'nan, and Yunfu.
-Zone	Asia/Chongqing	7:06:20	-	LMT	1928 # or Chungking
-			7:00	-	LONT	1980 May # Long-shu Time
-			8:00	PRC	C%sT
-# Xin-zang Time ("Xinjiang-Tibet Time")
+#
+# Xin-zang Time ("Xinjiang-Tibet Time") UT+6
+# Asia/Urumqi
+# This currently represents Kunlun Time as well,
+# as apparently the two regions have been the same since 1970.
 # The Gansu counties Aksay, Anxi, Dunhuang, Subei; west Qinghai;
 # the Guangdong counties  Xuwen, Haikang, Suixi, Lianjiang,
 # Zhanjiang, Wuchuan, Huazhou, Gaozhou, Maoming, Dianbai, and Xinyi;
 # east Tibet, including Lhasa, Chamdo, Shigaise, Jimsar, Shawan and Hutubi;
-# east Xinjiang, including Urumqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
+# east Xinjiang, including Ürümqi, Turpan, Karamay, Korla, Minfeng, Jinghe,
 # Wusu, Qiemo, Xinyan, Wulanwusu, Jinghe, Yumin, Tacheng, Tuoli, Emin,
 # Shihezi, Changji, Yanqi, Heshuo, Tuokexun, Tulufan, Shanshan, Hami,
 # Fukang, Kuitun, Kumukuli, Miquan, Qitai, and Turfan.
-Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
-			6:00	-	URUT	1980 May # Urumqi Time
-			8:00	PRC	C%sT
-# Kunlun Time
+#
+# Kunlun Time UT+5.5
+# Asia/Kashgar (currently a link to Asia/Urumqi)
 # West Tibet, including Pulan, Aheqi, Shufu, Shule;
 # West Xinjiang, including Aksu, Atushi, Yining, Hetian, Cele, Luopu, Nileke,
 # Zhaosu, Tekesi, Gongliu, Chabuchaer, Huocheng, Bole, Pishan, Suiding,
@@ -455,9 +465,9 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
 # population of Xinjiang, typically use "Xinjiang time" which is two
 # hours behind Beijing time, or UTC +0600. The government of the Xinjiang
 # Uyghur Autonomous Region, (XAUR, or just Xinjiang for short) as well as
-# local governments such as the Urumqi city government use both times in
+# local governments such as the Ürümqi city government use both times in
 # publications, referring to what is popularly called Xinjiang time as
-# "Urumqi time." When Uyghurs make an appointment in the Uyghur language
+# "Ürümqi time." When Uyghurs make an appointment in the Uyghur language
 # they almost invariably use Xinjiang time.
 #
 # (Their ethnic Han compatriots would typically have no clue of its
@@ -469,21 +479,6 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
 # the province not having dual times but four times in use at the same
 # time. Some areas remained on standard Xinjiang time or Beijing time and
 # others moving their clocks ahead.)
-#
-# ...an example of an official website using of Urumqi time.
-#
-# The first few lines of the Google translation of
-# 
-# http://www.fjysgl.gov.cn/show.aspx?id=2379&cid=39
-# 
-# (retrieved 2009-10-13)
-# > Urumqi fire seven people are missing the alleged losses of at least
-# > 500 million yuan
-# >
-# > (Reporter Dong Liu) the day before 20:20 or so (Urumqi Time 18:20),
-# > Urumqi City Department of International Plaza Luther Qiantang River
-# > burst fire. As of yesterday, 18:30, Urumqi City Fire officers and men
-# > have worked continuously for 22 hours...
 
 # From Luther Ma (2009-11-19):
 # With the risk of being redundant to previous answers these are the most common
@@ -494,7 +489,7 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
 # 3. Urumqi...
 # 4. Kashgar...
 # ...
-# 5. It seems that Uyghurs in Urumqi has been using Xinjiang since at least the
+# 5. It seems that Uyghurs in Ürümqi has been using Xinjiang since at least the
 # 1960's. I know of one Han, now over 50, who grew up in the surrounding
 # countryside and used Xinjiang time as a child.
 #
@@ -506,10 +501,55 @@ Zone	Asia/Urumqi	5:50:20	-	LMT	1928 # or Urumchi
 # Autonomous Region under the PRC. (Before that Uyghurs, of course, would also
 # not be using Beijing time, but some local time.)
 
-Zone	Asia/Kashgar	5:03:56	-	LMT	1928 # or Kashi or Kaxgar
-			5:30	-	KAST	1940	 # Kashgar Time
-			5:00	-	KAST	1980 May
+# From David Cochrane (2014-03-26):
+# Just a confirmation that Ürümqi time was implemented in Ürümqi on 1 Feb 1986:
+# http://content.time.com/time/magazine/article/0,9171,960684,00.html
+
+# From Luther Ma (2014-04-22):
+# I have interviewed numerous people of various nationalities and from
+# different localities in Xinjiang and can confirm the information in Guo's
+# report regarding Xinjiang, as well as the Time article reference by David
+# Cochrane.  Whether officially recognized or not (and both are officially
+# recognized), two separate times have been in use in Xinjiang since at least
+# the Cultural Revolution: Xinjiang Time (XJT), aka Ürümqi Time or local time;
+# and Beijing Time.  There is no confusion in Xinjiang as to which name refers
+# to which time. Both are widely used in the province, although in some
+# population groups might be use one to the exclusion of the other.  The only
+# problem is that computers and smart phones list Ürümqi (or Kashgar) as
+# having the same time as Beijing.
+
+# From Paul Eggert (2014-06-30):
+# In the early days of the PRC, Tibet was given its own time zone (UT+6) but
+# this was withdrawn in 1959 and never reinstated; see Tubten Khétsun,
+# Memories of life in Lhasa under Chinese Rule, Columbia U Press, ISBN
+# 978-0231142861 (2008), translator's introduction by Matthew Akester, p x.
+# As this is before our 1970 cutoff, Tibet doesn't need a separate zone.
+#
+# Xinjiang Time is well-documented as being officially recognized.  E.g., see
+# "The Working-Calendar for The Xinjiang Uygur Autonomous Region Government"
+#  (2014-04-22).
+# Unfortunately, we have no good records of time in Xinjiang before 1986.
+# During the 20th century parts of Xinjiang were ruled by the Qing dynasty,
+# the Republic of China, various warlords, the First and Second East Turkestan
+# Republics, the Soviet Union, the Kuomintang, and the People's Republic of
+# China, and tracking down all these organizations' timekeeping rules would be
+# quite a trick.  Approximate this lost history by a transition from LMT to
+# XJT at the start of 1928, the year of accession of the warlord Jin Shuren,
+# which happens to be the date given by Shanks & Pottenger (no doubt as a
+# guess) as the transition from LMT.  Ignore the usage of UT+8 before
+# 1986-02-01 under the theory that the transition date to UT+8 is unknown and
+# that the sort of users who prefer Asia/Urumqi now typically ignored the
+# UT+8 mandate back then.
+
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+# Beijing time, used throughout China; represented by Shanghai.
+Zone	Asia/Shanghai	8:05:43	-	LMT	1901
+			8:00	Shang	C%sT	1949
 			8:00	PRC	C%sT
+# Xinjiang time, used by many in western China; represented by Ürümqi / Ürümchi
+# / Wulumuqi.  (Please use Asia/Shanghai if you prefer Beijing time.)
+Zone	Asia/Urumqi	5:50:20	-	LMT	1928
+			6:00	-	XJT
 
 
 # Hong Kong (Xianggang)
@@ -524,15 +564,11 @@ Zone	Asia/Kashgar	5:03:56	-	LMT	1928 # or Kashi or Kaxgar
 # and incorrect rules. Although the exact switch over time is missing, I
 # think 3:30 is correct. The official DST record for Hong Kong can be
 # obtained from
-# 
 # http://www.hko.gov.hk/gts/time/Summertime.htm
-# .
 
 # From Arthur David Olson (2009-10-28):
 # Here are the dates given at
-# 
 # http://www.hko.gov.hk/gts/time/Summertime.htm
-# 
 # as of 2009-10-28:
 # Year        Period
 # 1941        1 Apr to 30 Sep
@@ -612,35 +648,113 @@ Zone	Asia/Hong_Kong	7:36:42 -	LMT	1904 Oct 30
 
 # Taiwan
 
-# Shanks & Pottenger write that Taiwan observed DST during 1945, when it
-# was still controlled by Japan.  This is hard to believe, but we don't
-# have any other information.
-
 # From smallufo (2010-04-03):
-# According to Taiwan's CWB,
-# 
+# According to Taiwan's CWB [Central Weather Bureau],
 # http://www.cwb.gov.tw/V6/astronomy/cdata/summert.htm
-# 
 # Taipei has DST in 1979 between July 1st and Sep 30.
 
-# From Arthur David Olson (2010-04-07):
-# Here's Google's translation of the table at the bottom of the "summert.htm" page:
-# Decade 	                                                    Name                      Start and end date
-# Republic of China 34 years to 40 years (AD 1945-1951 years) Summer Time               May 1 to September 30
-# 41 years of the Republic of China (AD 1952)                 Daylight Saving Time      March 1 to October 31
-# Republic of China 42 years to 43 years (AD 1953-1954 years) Daylight Saving Time      April 1 to October 31
-# In the 44 years to 45 years (AD 1955-1956 years)            Daylight Saving Time      April 1 to September 30
-# Republic of China 46 years to 48 years (AD 1957-1959)       Summer Time               April 1 to September 30
-# Republic of China 49 years to 50 years (AD 1960-1961)       Summer Time               June 1 to September 30
-# Republic of China 51 years to 62 years (AD 1962-1973 years) Stop Summer Time
-# Republic of China 63 years to 64 years (1974-1975 AD)       Daylight Saving Time      April 1 to September 30
-# Republic of China 65 years to 67 years (1976-1978 AD)       Stop Daylight Saving Time
-# Republic of China 68 years (AD 1979)                        Daylight Saving Time      July 1 to September 30
-# Republic of China since 69 years (AD 1980)                  Stop Daylight Saving Time
+# From Yu-Cheng Chuang (2013-07-12):
+# On Dec 28, 1895, the Meiji Emperor announced Ordinance No. 167 of
+# Meiji Year 28 "The clause about standard time", mentioned that
+# Taiwan and Penghu Islands, as well as Yaeyama and Miyako Islands
+# (both in Okinawa) adopt the Western Standard Time which is based on
+# 120E. The adoption began from Jan 1, 1896. The original text can be
+# found on Wikisource:
+# http://ja.wikisource.org/wiki/標準時ニ關スル件_(公布時)
+# ... This could be the first adoption of time zone in Taiwan, because
+# during the Qing Dynasty, it seems that there was no time zone
+# declared officially.
+#
+# Later, in the beginning of World War II, on Sep 25, 1937, the Showa
+# Emperor announced Ordinance No. 529 of Showa Year 12 "The clause of
+# revision in the ordinance No. 167 of Meiji year 28 about standard
+# time", in which abolished the adoption of Western Standard Time in
+# western islands (listed above), which means the whole Japan
+# territory, including later occupations, adopt Japan Central Time
+# (UTC+9). The adoption began on Oct 1, 1937. The original text can
+# be found on Wikisource:
+# http://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
+#
+# That is, the time zone of Taipei switched to UTC+9 on Oct 1, 1937.
+
+# From Yu-Cheng Chuang (2014-07-02):
+# I've found more evidence about when the time zone was switched from UTC+9
+# back to UTC+8 after WW2.  I believe it was on Sep 21, 1945.  In a document
+# during Japanese era [1] in which the officer told the staff to change time
+# zone back to Western Standard Time (UTC+8) on Sep 21.  And in another
+# history page of National Cheng Kung University [2], on Sep 21 there is a
+# note "from today, switch back to Western Standard Time".  From these two
+# materials, I believe that the time zone change happened on Sep 21.  And
+# today I have found another monthly journal called "The Astronomical Herald"
+# from The Astronomical Society of Japan [3] in which it mentioned the fact
+# that:
+#
+# 1. Standard Time of the Country (Japan) was adopted on Jan 1, 1888, using
+# the time at 135E (GMT+9)
+#
+# 2. Standard Time of the Country was renamed to Central Standard Time, on Jan
+# 1, 1898, and on the same day, the new territories Taiwan and Penghu islands,
+# as well as Yaeyama and Miyako islands, adopted a new time zone called
+# Western Standard Time, which is in GMT+8.
+#
+# 3. Western Standard Time was deprecated on Sep 30, 1937. From then all the
+# territories of Japan adopted the same time zone, which is Central Standard
+# Time.
+#
+# [1] Academica Historica, Taiwan:
+# http://163.29.208.22:8080/govsaleShowImage/connect_img.php?s=00101738900090036&e=00101738900090037
+# [2] Nat'l Cheng Kung University 70th Anniversary Special Site:
+# http://www.ncku.edu.tw/~ncku70/menu/001/01_01.htm
+# [3] Yukio Niimi, The Standard Time in Japan (1997), p.475:
+# http://www.asj.or.jp/geppou/archive_open/1997/pdf/19971001c.pdf
+
+# Yu-Cheng Chuang (2014-07-03):
+# I finally have found the real official gazette about changing back to
+# Western Standard Time on Sep 21 in Taiwan.  It's Taiwan Governor-General
+# Bulletin No. 386 in Showa 20 years (1945), published on Sep 19, 1945. [1] ...
+# [It] abolishes Bulletin No. 207 in Showa 12 years (1937), which is a local
+# bulletin in Taiwan for that Ordinance No. 529. It also mentioned that 1am on
+# Sep 21, 1945 will be 12am on Sep 21.  I think this bulletin is much more
+# official than the one I mentioned in my first mail, because it's from the
+# top-level government in Taiwan. If you're going to quote any resource, this
+# would be a good one.
+# [1] Taiwan Governor-General Gazette, No. 1018, Sep 19, 1945:
+# http://db2.th.gov.tw/db2/view/viewImg.php?imgcode=0072031018a&num=19&bgn=019&end=019&otherImg=&type=gener
+
+# From Yu-Cheng Chuang (2014-07-02):
+# In 1946, DST in Taiwan was from May 15 and ended on Sep 30. The info from
+# Central Weather Bureau website was not correct.
+#
+# Original Bulletin:
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=03502F0AKM1AF
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=0350300AKM1B0 (cont.)
+#
+# In 1947, DST in Taiwan was expanded to Oct 31. There is a backup of that
+# telegram announcement from Taiwan Province Government:
+#
+# http://subtpg.tpg.gov.tw/og/image2.asp?f=0360310AKZ431
+#
+# Here is a brief translation:
+#
+#   The Summer Time this year is adopted from midnight Apr 15 until Sep 20
+#   midnight. To save (energy?) consumption, we're expanding Summer Time
+#   adoption till Oct 31 midnight.
+#
+# The Central Weather Bureau website didn't mention that, however it can
+# be found from historical government announcement database.
+
+# From Paul Eggert (2014-07-03):
+# As per Yu-Cheng Chuang, say that Taiwan was at UT+9 from 1937-10-01
+# until 1945-09-21 at 01:00, overriding Shanks & Pottenger.
+# Likewise, use Yu-Cheng Chuang's data for DST in Taiwan.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Taiwan	1945	1951	-	May	1	0:00	1:00	D
-Rule	Taiwan	1945	1951	-	Oct	1	0:00	0	S
+Rule	Taiwan	1946	only	-	May	15	0:00	1:00	D
+Rule	Taiwan	1946	only	-	Oct	1	0:00	0	S
+Rule	Taiwan	1947	only	-	Apr	15	0:00	1:00	D
+Rule	Taiwan	1947	only	-	Nov	1	0:00	0	S
+Rule	Taiwan	1948	1951	-	May	1	0:00	1:00	D
+Rule	Taiwan	1948	1951	-	Oct	1	0:00	0	S
 Rule	Taiwan	1952	only	-	Mar	1	0:00	1:00	D
 Rule	Taiwan	1952	1954	-	Nov	1	0:00	0	S
 Rule	Taiwan	1953	1959	-	Apr	1	0:00	1:00	D
@@ -648,11 +762,14 @@ Rule	Taiwan	1955	1961	-	Oct	1	0:00	0	S
 Rule	Taiwan	1960	1961	-	Jun	1	0:00	1:00	D
 Rule	Taiwan	1974	1975	-	Apr	1	0:00	1:00	D
 Rule	Taiwan	1974	1975	-	Oct	1	0:00	0	S
-Rule	Taiwan	1979	only	-	Jun	30	0:00	1:00	D
-Rule	Taiwan	1979	only	-	Sep	30	0:00	0	S
+Rule	Taiwan	1979	only	-	Jul	1	0:00	1:00	D
+Rule	Taiwan	1979	only	-	Oct	1	0:00	0	S
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Taipei	8:06:00 -	LMT	1896 # or Taibei or T'ai-pei
+# Taipei or Taibei or T'ai-pei
+Zone	Asia/Taipei	8:06:00 -	LMT	1896 Jan  1
+			8:00	-	JWST	1937 Oct  1
+			9:00	-	JST	1945 Sep 21  1:00
 			8:00	Taiwan	C%sT
 
 # Macau (Macao, Aomen)
@@ -672,7 +789,7 @@ Rule	Macau	1975	1977	-	Apr	Sun>=15	3:30	1:00	S
 Rule	Macau	1978	1980	-	Apr	Sun>=15	0:00	1:00	S
 Rule	Macau	1978	1980	-	Oct	Sun>=15	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Macau	7:34:20 -	LMT	1912
+Zone	Asia/Macau	7:34:20 -	LMT	1912 Jan  1
 			8:00	Macau	MO%sT	1999 Dec 20 # return to China
 			8:00	PRC	C%sT
 
@@ -721,7 +838,7 @@ Link	Asia/Nicosia	Europe/Nicosia
 # republic has changed its time zone back to that of Moscow.  As a result it
 # is now just four hours ahead of Greenwich Mean Time, rather than five hours
 # ahead.  The switch was decreed by the pro-Western president of Georgia,
-# Mikhail Saakashvili, who said the change was partly prompted by the process
+# Mikheil Saakashvili, who said the change was partly prompted by the process
 # of integration into Europe.
 
 # From Teimuraz Abashidze (2005-11-07):
@@ -734,29 +851,31 @@ Link	Asia/Nicosia	Europe/Nicosia
 # I don't know what can be done, especially knowing that some years ago our
 # DST rules where changed THREE TIMES during one month.
 
+# Milne 1899 says Tbilisi (Tiflis) time was 2:59:05.7.
+# Byalokoz 1919 says Georgia was 2:59:11.
+# Go with Byalokoz.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Tbilisi	2:59:16 -	LMT	1880
-			2:59:16	-	TBMT	1924 May  2 # Tbilisi Mean Time
+Zone	Asia/Tbilisi	2:59:11 -	LMT	1880
+			2:59:11	-	TBMT	1924 May  2 # Tbilisi Mean Time
 			3:00	-	TBIT	1957 Mar    # Tbilisi Time
-			4:00 RussiaAsia TBI%sT	1991 Mar 31 2:00s
+			4:00 RussiaAsia TBI%sT	1991 Mar 31  2:00s
 			3:00	1:00	TBIST	1991 Apr  9 # independence
-			3:00 RussiaAsia GE%sT	1992 # Georgia Time
+			3:00 RussiaAsia GE%sT	1992        # Georgia Time
 			3:00 E-EurAsia	GE%sT	1994 Sep lastSun
 			4:00 E-EurAsia	GE%sT	1996 Oct lastSun
 			4:00	1:00	GEST	1997 Mar lastSun
 			4:00 E-EurAsia	GE%sT	2004 Jun 27
-			3:00 RussiaAsia	GE%sT	2005 Mar lastSun 2:00
+			3:00 RussiaAsia	GE%sT	2005 Mar lastSun  2:00
 			4:00	-	GET
 
 # East Timor
 
 # See Indonesia for the 1945 transition.
 
-# From Joao Carrascalao, brother of the former governor of East Timor, in
-# 
+# From João Carrascalão, brother of the former governor of East Timor, in
 # East Timor may be late for its millennium
-#  (1999-12-26/31):
+#  (1999-12-26/31):
 # Portugal tried to change the time forward in 1974 because the sun
 # rises too early but the suggestion raised a lot of problems with the
 # Timorese and I still don't think it would work today because it
@@ -766,25 +885,25 @@ Zone	Asia/Tbilisi	2:59:16 -	LMT	1880
 # We don't have any record of the above attempt.
 # Most likely our records are incomplete, but we have no better data.
 
-# 
 # From Manoel de Almeida e Silva, Deputy Spokesman for the UN Secretary-General
-# (2000-08-16):
+# http://www.hri.org/news/world/undh/2000/00-08-16.undh.html
+# (2000-08-16):
 # The Cabinet of the East Timor Transition Administration decided
 # today to advance East Timor's time by one hour.  The time change,
 # which will be permanent, with no seasonal adjustment, will happen at
 # midnight on Saturday, September 16.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Dili	8:22:20 -	LMT	1912
+Zone	Asia/Dili	8:22:20 -	LMT	1912 Jan  1
 			8:00	-	TLT	1942 Feb 21 23:00 # E Timor Time
 			9:00	-	JST	1945 Sep 23
 			9:00	-	TLT	1976 May  3
-			8:00	-	WITA	2000 Sep 17 00:00
+			8:00	-	WITA	2000 Sep 17  0:00
 			9:00	-	TLT
 
 # India
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
+Zone	Asia/Kolkata	5:53:28 -	LMT	1880        # Kolkata
 			5:53:20	-	HMT	1941 Oct    # Howrah Mean Time?
 			6:30	-	BURT	1942 May 15 # Burma Time
 			5:30	-	IST	1942 Sep
@@ -798,7 +917,7 @@ Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
 # Indonesia
 #
 # From Gwillim Law (2001-05-28), overriding Shanks & Pottenger:
-# 
+# http://www.sumatera-inc.com/go_to_invest/about_indonesia.asp#standtime
 # says that Indonesia's time zones changed on 1988-01-01.  Looking at some
 # time zone maps, I think that must refer to Western Borneo (Kalimantan Barat
 # and Kalimantan Tengah) switching from UTC+8 to UTC+7.
@@ -810,7 +929,7 @@ Zone	Asia/Kolkata	5:53:28 -	LMT	1880	# Kolkata
 # other formal surrender ceremonies were September 9, 11, and 13, plus
 # September 12 for the regional surrender to Mountbatten in Singapore.
 # These would be the earliest possible times for a change.
-# Regimes horaires pour le monde entier, by Henri Le Corre, (Editions
+# Régimes horaires pour le monde entier, by Henri Le Corre, (Éditions
 # Traditionnelles, 1987, Paris) says that Java and Madura switched
 # from JST to UTC+07:30 on 1945-09-23, and gives 1944-09-01 for Jayapura
 # (Hollandia).  For now, assume all Indonesian locations other than Jayapura
@@ -835,7 +954,7 @@ Zone Asia/Jakarta	7:07:12 -	LMT	1867 Aug 10
 # Shanks & Pottenger say the next transition was at 1924 Jan 1 0:13,
 # but this must be a typo.
 			7:07:12	-	BMT	1923 Dec 31 23:47:12 # Batavia
-			7:20	-	JAVT	1932 Nov	 # Java Time
+			7:20	-	JAVT	1932 Nov    # Java Time
 			7:30	-	WIB	1942 Mar 23
 			9:00	-	JST	1945 Sep 23
 			7:30	-	WIB	1948 May
@@ -861,7 +980,7 @@ Zone Asia/Makassar	7:57:36 -	LMT	1920
 # Maluku Islands, West Papua, Papua
 Zone Asia/Jayapura	9:22:48 -	LMT	1932 Nov
 			9:00	-	WIT	1944 Sep  1
-			9:30	-	CST	1964
+			9:30	-	ACST	1964
 			9:00	-	WIT
 
 # Iran
@@ -927,7 +1046,7 @@ Zone Asia/Jayapura	9:22:48 -	LMT	1932 Nov
 # Several of my users have reported that Iran will not observe DST anymore:
 # http://www.irna.ir/en/news/view/line-17/0603193812164948.htm
 #
-# From Reuters (2007-09-16), with a heads-up from Jesper Norgaard Welen:
+# From Reuters (2007-09-16), with a heads-up from Jesper Nørgaard Welen:
 # ... the Guardian Council ... approved a law on Sunday to re-introduce
 # daylight saving time ...
 # http://uk.reuters.com/article/oilRpt/idUKBLA65048420070916
@@ -993,7 +1112,7 @@ Rule	Iran	2036	2037	-	Mar	21	0:00	1:00	D
 Rule	Iran	2036	2037	-	Sep	21	0:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tehran	3:25:44	-	LMT	1916
-			3:25:44	-	TMT	1946	# Tehran Mean Time
+			3:25:44	-	TMT	1946     # Tehran Mean Time
 			3:30	-	IRST	1977 Nov
 			4:00	Iran	IR%sT	1979
 			3:30	Iran	IR%sT
@@ -1018,17 +1137,11 @@ Zone	Asia/Tehran	3:25:44	-	LMT	1916
 # From Steffen Thorsen (2008-03-10):
 # The cabinet in Iraq abolished DST last week, according to the following
 # news sources (in Arabic):
-# 
 # http://www.aljeeran.net/wesima_articles/news-20080305-98602.html
-# 
-# 
 # http://www.aswataliraq.info/look/article.tpl?id=2047&IdLanguage=17&IdPublication=4&NrArticle=71743&NrIssue=1&NrSection=10
-# 
 #
 # We have published a short article in English about the change:
-# 
 # http://www.timeanddate.com/news/time/iraq-dumps-daylight-saving.html
-# 
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Iraq	1982	only	-	May	1	0:00	1:00	D
@@ -1037,14 +1150,14 @@ Rule	Iraq	1983	only	-	Mar	31	0:00	1:00	D
 Rule	Iraq	1984	1985	-	Apr	1	0:00	1:00	D
 Rule	Iraq	1985	1990	-	Sep	lastSun	1:00s	0	S
 Rule	Iraq	1986	1990	-	Mar	lastSun	1:00s	1:00	D
-# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the `:01' is a typo.
+# IATA SSIM (1991/1996) says Apr 1 12:01am UTC; guess the ':01' is a typo.
 # Shanks & Pottenger say Iraq did not observe DST 1992/1997; ignore this.
 #
 Rule	Iraq	1991	2007	-	Apr	 1	3:00s	1:00	D
 Rule	Iraq	1991	2007	-	Oct	 1	3:00s	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Baghdad	2:57:40	-	LMT	1890
-			2:57:36	-	BMT	1918	    # Baghdad Mean Time?
+			2:57:36	-	BMT	1918     # Baghdad Mean Time?
 			3:00	-	AST	1982 May
 			3:00	Iraq	A%sT
 
@@ -1272,7 +1385,7 @@ Rule	Zion	2013	max	-	Oct	lastSun	2:00	0	S
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Jerusalem	2:20:54 -	LMT	1880
-			2:20:40	-	JMT	1918	# Jerusalem Mean Time?
+			2:20:40	-	JMT	1918 # Jerusalem Mean Time?
 			2:00	Zion	I%sT
 
 
@@ -1281,15 +1394,15 @@ Zone	Asia/Jerusalem	2:20:54 -	LMT	1880
 
 # Japan
 
-# `9:00' and `JST' is from Guy Harris.
+# '9:00' and 'JST' is from Guy Harris.
 
 # From Paul Eggert (1995-03-06):
 # Today's _Asahi Evening News_ (page 4) reports that Japan had
-# daylight saving between 1948 and 1951, but ``the system was discontinued
-# because the public believed it would lead to longer working hours.''
+# daylight saving between 1948 and 1951, but "the system was discontinued
+# because the public believed it would lead to longer working hours."
 
-# From Mayumi Negishi in the 2005-08-10 Japan Times
-# :
+# From Mayumi Negishi in the 2005-08-10 Japan Times:
+# http://www.japantimes.co.jp/cgi-bin/getarticle.pl5?nn20050810f2.htm
 # Occupation authorities imposed daylight-saving time on Japan on
 # [1948-05-01]....  But lack of prior debate and the execution of
 # daylight-saving time just three days after the bill was passed generated
@@ -1313,7 +1426,8 @@ Rule	Japan	1950	1951	-	May	Sun>=1	2:00	1:00	D
 
 # From Hideyuki Suzuki (1998-11-09):
 # 'Tokyo' usually stands for the former location of Tokyo Astronomical
-# Observatory: E 139 44' 40".90 (9h 18m 58s.727), N 35 39' 16".0.
+# Observatory: 139 degrees 44' 40.90" E (9h 18m 58.727s),
+# 35 degrees 39' 16.0" N.
 # This data is from 'Rika Nenpyou (Chronological Scientific Tables) 1996'
 # edited by National Astronomical Observatory of Japan....
 # JST (Japan Standard Time) has been used since 1888-01-01 00:00 (JST).
@@ -1321,10 +1435,10 @@ Rule	Japan	1950	1951	-	May	Sun>=1	2:00	1:00	D
 
 # From Hideyuki Suzuki (1998-11-16):
 # The ordinance No. 51 (1886) established "standard time" in Japan,
-# which stands for the time on E 135 degree.
+# which stands for the time on 135 degrees E.
 # In the ordinance No. 167 (1895), "standard time" was renamed to "central
 # standard time".  And the same ordinance also established "western standard
-# time", which stands for the time on E 120 degree....  But "western standard
+# time", which stands for the time on 120 degrees E....  But "western standard
 # time" was abolished in the ordinance No. 529 (1937).  In the ordinance No.
 # 167, there is no mention regarding for what place western standard time is
 # standard....
@@ -1332,27 +1446,33 @@ Rule	Japan	1950	1951	-	May	Sun>=1	2:00	1:00	D
 # I wrote "ordinance" above, but I don't know how to translate.
 # In Japanese it's "chokurei", which means ordinance from emperor.
 
-# Shanks & Pottenger claim JST in use since 1896, and that a few
-# places (e.g. Ishigaki) use +0800; go with Suzuki.  Guess that all
-# ordinances took effect on Jan 1.
+# From Yu-Cheng Chuang (2013-07-12):
+# ...the Meiji Emperor announced Ordinance No. 167 of Meiji Year 28 "The clause
+# about standard time" ... The adoption began from Jan 1, 1896.
+# http://ja.wikisource.org/wiki/標準時ニ關スル件_(公布時)
+#
+# ...the Showa Emperor announced Ordinance No. 529 of Showa Year 12 ... which
+# means the whole Japan territory, including later occupations, adopt Japan
+# Central Time (UTC+9). The adoption began on Oct 1, 1937.
+# http://ja.wikisource.org/wiki/明治二十八年勅令第百六十七號標準時ニ關スル件中改正ノ件
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Tokyo	9:18:59	-	LMT	1887 Dec 31 15:00u
-			9:00	-	JST	1896
-			9:00	-	CJT	1938
+			9:00	-	JST	1896 Jan  1
+			9:00	-	JCST	1937 Oct  1
 			9:00	Japan	J%sT
 # Since 1938, all Japanese possessions have been like Asia/Tokyo.
 
 # Jordan
 #
-# From 
-# Jordan Week (1999-07-01)  via Steffen Thorsen (1999-09-09):
+# From 
+# Jordan Week (1999-07-01) via Steffen Thorsen (1999-09-09):
 # Clocks in Jordan were forwarded one hour on Wednesday at midnight,
 # in accordance with the government's decision to implement summer time
 # all year round.
 #
-# From 
-# Jordan Week (1999-09-30)  via Steffen Thorsen (1999-11-09):
+# From 
+# Jordan Week (1999-09-30) via Steffen Thorsen (1999-11-09):
 # Winter time starts today Thursday, 30 September. Clocks will be turned back
 # by one hour.  This is the latest government decision and it's final!
 # The decision was taken because of the increase in working hours in
@@ -1372,9 +1492,7 @@ Zone	Asia/Tokyo	9:18:59	-	LMT	1887 Dec 31 15:00u
 
 # From Steffen Thorsen (2009-04-02):
 # This single one might be good enough, (2009-03-24, Arabic):
-# 
 # http://petra.gov.jo/Artical.aspx?Lng=2&Section=8&Artical=95279
-# 
 #
 # Google's translation:
 #
@@ -1465,9 +1583,8 @@ Zone	Asia/Amman	2:23:44 -	LMT	1931
 # - Qyzylorda switched from +5:00 to +6:00 on 1992-01-19 02:00.
 # - Oral switched from +5:00 to +4:00 in spring 1989.
 
-# 
-# From Kazakhstan Embassy's News Bulletin #11 (2005-03-21):
-# 
+# From Kazakhstan Embassy's News Bulletin #11
+#  (2005-03-21):
 # The Government of Kazakhstan passed a resolution March 15 abolishing
 # daylight saving time citing lack of economic benefits and health
 # complications coupled with a decrease in productivity.
@@ -1500,10 +1617,10 @@ Zone	Asia/Qyzylorda	4:21:52 -	LMT	1924 May  2
 			6:00	-	KIZT	1982 Apr  1
 			5:00 RussiaAsia	KIZ%sT	1991
 			5:00	-	KIZT	1991 Dec 16 # independence
-			5:00	-	QYZT	1992 Jan 19 2:00
+			5:00	-	QYZT	1992 Jan 19  2:00
 			6:00 RussiaAsia	QYZ%sT	2005 Mar 15
 			6:00	-	QYZT
-# Aqtobe (aka Aktobe, formerly Akt'ubinsk)
+# Aqtobe (aka Aktobe, formerly Aktyubinsk)
 Zone	Asia/Aqtobe	3:48:40	-	LMT	1924 May  2
 			4:00	-	AKTT	1930 Jun 21 # Aktyubinsk Time
 			5:00	-	AKTT	1981 Apr  1
@@ -1523,7 +1640,7 @@ Zone	Asia/Aqtau	3:21:04	-	LMT	1924 May  2
 			6:00	-	SHET	1982 Apr  1
 			5:00 RussiaAsia	SHE%sT	1991
 			5:00	-	SHET	1991 Dec 16 # independence
-			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun 2:00 # Aqtau Time
+			5:00 RussiaAsia	AQT%sT	1995 Mar lastSun  2:00 # Aqtau Time
 			4:00 RussiaAsia	AQT%sT	2005 Mar 15
 			5:00	-	AQTT
 # West Kazakhstan
@@ -1532,7 +1649,7 @@ Zone	Asia/Oral	3:25:24	-	LMT	1924 May  2 # or Ural'sk
 			5:00	-	URAT	1981 Apr  1
 			5:00	1:00	URAST	1981 Oct  1
 			6:00	-	URAT	1982 Apr  1
-			5:00 RussiaAsia	URA%sT	1989 Mar 26 2:00
+			5:00 RussiaAsia	URA%sT	1989 Mar 26  2:00
 			4:00 RussiaAsia	URA%sT	1991
 			4:00	-	URAT	1991 Dec 16 # independence
 			4:00 RussiaAsia	ORA%sT	2005 Mar 15 # Oral Time
@@ -1543,7 +1660,7 @@ Zone	Asia/Oral	3:25:24	-	LMT	1924 May  2 # or Ural'sk
 
 # From Paul Eggert (2005-08-15):
 # According to an article dated today in the Kyrgyzstan Development Gateway
-# 
+# http://eng.gateway.kg/cgi-bin/page.pl?id=1&story_name=doc9979.shtml
 # Kyrgyzstan is canceling the daylight saving time system.  I take the article
 # to mean that they will leave their clocks at 6 hours ahead of UTC.
 # From Malik Abdugaliev (2005-09-21):
@@ -1558,17 +1675,17 @@ Rule	Kyrgyz	1997	2004	-	Oct	lastSun	2:30	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Bishkek	4:58:24 -	LMT	1924 May  2
 			5:00	-	FRUT	1930 Jun 21 # Frunze Time
-			6:00 RussiaAsia FRU%sT	1991 Mar 31 2:00s
-			5:00	1:00	FRUST	1991 Aug 31 2:00 # independence
-			5:00	Kyrgyz	KG%sT	2005 Aug 12    # Kyrgyzstan Time
+			6:00 RussiaAsia FRU%sT	1991 Mar 31  2:00s
+			5:00	1:00	FRUST	1991 Aug 31  2:00 # independence
+			5:00	Kyrgyz	KG%sT	2005 Aug 12 # Kyrgyzstan Time
 			6:00	-	KGT
 
 ###############################################################################
 
 # Korea (North and South)
 
-# From Annie I. Bang (2006-07-10) in
-# :
+# From Annie I. Bang (2006-07-10):
+# http://www.koreaherald.co.kr/SITE/data/html_dir/2006/07/10/200607100012.asp
 # The Ministry of Commerce, Industry and Energy has already
 # commissioned a research project [to reintroduce DST] and has said
 # the system may begin as early as 2008....  Korea ran a daylight
@@ -1581,19 +1698,29 @@ Rule	ROK	1960	only	-	Sep	13	0:00	0	S
 Rule	ROK	1987	1988	-	May	Sun>=8	0:00	1:00	D
 Rule	ROK	1987	1988	-	Oct	Sun>=8	0:00	0	S
 
+# From Paul Eggert (2014-07-01):
+# The following entries are from Shanks & Pottenger, except that I
+# guessed that time zone abbreviations through 1945 followed the same
+# rules as discussed under Taiwan, with nominal switches from JST to KST
+# when the respective cities were taken over by the Allies after WWII.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Seoul	8:27:52	-	LMT	1890
 			8:30	-	KST	1904 Dec
-			9:00	-	KST	1928
+			9:00	-	JCST	1928
 			8:30	-	KST	1932
+			9:00	-	JCST	1937 Oct  1
+			9:00	-	JST	1945 Sep  8
 			9:00	-	KST	1954 Mar 21
 			8:00	ROK	K%sT	1961 Aug 10
 			8:30	-	KST	1968 Oct
 			9:00	ROK	K%sT
 Zone	Asia/Pyongyang	8:23:00 -	LMT	1890
 			8:30	-	KST	1904 Dec
-			9:00	-	KST	1928
+			9:00	-	JCST	1928
 			8:30	-	KST	1932
+			9:00	-	JCST	1937 Oct  1
+			9:00	-	JST	1945 Aug 24
 			9:00	-	KST	1954 Mar 21
 			8:00	-	KST	1961 Aug 10
 			9:00	-	KST
@@ -1602,21 +1729,13 @@ Zone	Asia/Pyongyang	8:23:00 -	LMT	1890
 
 # Kuwait
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# From the Arab Times (2007-03-14):
-# The Civil Service Commission (CSC) has approved a proposal forwarded
-# by MP Ahmad Baqer on implementing the daylight saving time (DST) in
-# Kuwait starting from April until the end of Sept this year, reports Al-Anba.
-# .
-# From Paul Eggert (2007-03-29):
-# We don't know the details, or whether the approval means it'll happen,
-# so for now we assume no DST.
 Zone	Asia/Kuwait	3:11:56 -	LMT	1950
 			3:00	-	AST
 
 # Laos
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9 # or Viangchan
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+Zone	Asia/Vientiane	6:50:24 -	LMT	1906 Jun  9       # or Viangchan
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
@@ -1657,8 +1776,8 @@ Rule	NBorneo	1935	1941	-	Sep	14	0:00	0:20	TS # one-Third Summer
 Rule	NBorneo	1935	1941	-	Dec	14	0:00	0	-
 #
 # peninsular Malaysia
-# The data here are taken from Mok Ly Yng (2003-10-30)
-# .
+# taken from Mok Ly Yng (2003-10-30)
+# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Kuala_Lumpur	6:46:46 -	LMT	1901 Jan  1
 			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
@@ -1670,12 +1789,12 @@ Zone Asia/Kuala_Lumpur	6:46:46 -	LMT	1901 Jan  1
 			7:30	-	MALT	1982 Jan  1
 			8:00	-	MYT	# Malaysia Time
 # Sabah & Sarawak
-# From Paul Eggert (2006-03-22):
-# The data here are mostly from Shanks & Pottenger, but the 1942, 1945 and 1982
-# transition dates are from Mok Ly Yng.
+# From Paul Eggert (2014-08-12):
+# The data entries here are mostly from Shanks & Pottenger, but the 1942, 1945
+# and 1982 transition dates are from Mok Ly Yng.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Asia/Kuching	7:21:20	-	LMT	1926 Mar
-			7:30	-	BORT	1933	# Borneo Time
+			7:30	-	BORT	1933        # Borneo Time
 			8:00	NBorneo	BOR%sT	1942 Feb 16
 			9:00	-	JST	1945 Sep 12
 			8:00	-	BORT	1982 Jan  1
@@ -1683,22 +1802,21 @@ Zone Asia/Kuching	7:21:20	-	LMT	1926 Mar
 
 # Maldives
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
-			4:54:00	-	MMT	1960	# Male Mean Time
-			5:00	-	MVT		# Maldives Time
+Zone	Indian/Maldives	4:54:00 -	LMT	1880 # Male
+			4:54:00	-	MMT	1960 # Male Mean Time
+			5:00	-	MVT	# Maldives Time
 
 # Mongolia
 
 # Shanks & Pottenger say that Mongolia has three time zones, but
-# usno1995 and the CIA map Standard Time Zones of the World (2005-03)
-# both say that it has just one.
+# The USNO (1995-12-21) and the CIA map Standard Time Zones of the World
+# (2005-03) both say that it has just one.
 
 # From Oscar van Vlijmen (1999-12-11):
-# 
 # General Information Mongolia
-#  (1999-09)
+#  (1999-09)
 # "Time: Mongolia has two time zones. Three westernmost provinces of
-# Bayan-Ulgii, Uvs, and Hovd are one hour earlier than the capital city, and
+# Bayan-Ölgii, Uvs, and Hovd are one hour earlier than the capital city, and
 # the rest of the country follows the Ulaanbaatar time, which is UTC/GMT plus
 # eight hours."
 
@@ -1709,7 +1827,7 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
 # of implementation may have been different....
 # Some maps in the past have indicated that there was an additional time
 # zone in the eastern part of Mongolia, including the provinces of Dornod,
-# Suhbaatar, and possibly Khentij.
+# Sükhbaatar, and possibly Khentii.
 
 # From Paul Eggert (1999-12-15):
 # Naming and spelling is tricky in Mongolia.
@@ -1723,10 +1841,10 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
 # (adopted DST on 2001-04-27 02:00 local time, ending 2001-09-28),
 # there are three time zones.
 #
-# Provinces [at 7:00]: Bayan-ulgii, Uvs, Khovd, Zavkhan, Govi-Altai
-# Provinces [at 8:00]: Khovsgol, Bulgan, Arkhangai, Khentii, Tov,
-#	Bayankhongor, Ovorkhangai, Dundgovi, Dornogovi, Omnogovi
-# Provinces [at 9:00]: Dornod, Sukhbaatar
+# Provinces [at 7:00]: Bayan-Ölgii, Uvs, Khovd, Zavkhan, Govi-Altai
+# Provinces [at 8:00]: Khövsgöl, Bulgan, Arkhangai, Khentii, Töv,
+#	Bayankhongor, Övörkhangai, Dundgovi, Dornogovi, Ömnögovi
+# Provinces [at 9:00]: Dornod, Sükhbaatar
 #
 # [The province of Selenge is omitted from the above lists.]
 
@@ -1743,16 +1861,16 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
 # We have wildly conflicting information about Mongolia's time zones.
 # Bill Bonnet (2005-05-19) reports that the US Embassy in Ulaanbaatar says
 # there is only one time zone and that DST is observed, citing Microsoft
-# Windows XP as the source.  Risto Nykanen (2005-05-16) reports that
+# Windows XP as the source.  Risto Nykänen (2005-05-16) reports that
 # travelmongolia.org says there are two time zones (UTC+7, UTC+8) with no DST.
 # Oscar van Vlijmen (2005-05-20) reports that the Mongolian Embassy in
 # Washington, DC says there are two time zones, with DST observed.
 # He also found
-# 
+# http://ubpost.mongolnews.mn/index.php?subaction=showcomments&id=1111634894&archive=&start_from=&ucat=1&
 # which also says that there is DST, and which has a comment by "Toddius"
 # (2005-03-31 06:05 +0700) saying "Mongolia actually has 3.5 time zones.
 # The West (OLGII) is +7 GMT, most of the country is ULAT is +8 GMT
-# and some Eastern provinces are +9 GMT but Sukhbaatar Aimag is SUHK +8.5 GMT.
+# and some Eastern provinces are +9 GMT but Sükhbaatar Aimag is SUHK +8.5 GMT.
 # The SUKH timezone is new this year, it is one of the few things the
 # parliament passed during the tumultuous winter session."
 # For now, let's ignore this information, until we have more confirmation.
@@ -1768,29 +1886,23 @@ Zone	Indian/Maldives	4:54:00 -	LMT	1880	# Male
 # +08:00 instead. Different sources appear to disagree with the tz
 # database on this, e.g.:
 #
-# 
 # http://www.timeanddate.com/worldclock/city.html?n=1026
-# 
-# 
 # http://www.worldtimeserver.com/current_time_in_MN.aspx
-# 
 #
 # both say GMT+08:00.
 
 # From Steffen Thorsen (2008-03-31):
 # eznis airways, which operates several domestic flights, has a flight
 # schedule here:
-# 
 # http://www.eznis.com/Container.jsp?id=112
-# 
 # (click the English flag for English)
 #
-# There it appears that flights between Choibalsan and Ulaanbatar arrive
+# There it appears that flights between Choibalsan and Ulaanbaatar arrive
 # about 1:35 - 1:50 hours later in local clock time, no matter the
-# direction, while Ulaanbaatar-Khvod takes 2 hours in the Eastern
-# direction and 3:35 back, which indicates that Ulaanbatar and Khvod are
+# direction, while Ulaanbaatar-Khovd takes 2 hours in the Eastern
+# direction and 3:35 back, which indicates that Ulaanbaatar and Khovd are
 # in different time zones (like we know about), while Choibalsan and
-# Ulaanbatar are in the same time zone (correction needed).
+# Ulaanbaatar are in the same time zone (correction needed).
 
 # From Arthur David Olson (2008-05-19):
 # Assume that Choibalsan is indeed offset by 8:00.
@@ -1806,7 +1918,7 @@ Rule	Mongol	1983	only	-	Oct	1	0:00	0	-
 # (1996-09) says 1996-10-25.  Go with Shanks & Pottenger through 1998.
 #
 # Shanks & Pottenger say that the Sept. 1984 through Sept. 1990 switches
-# in Choibalsan (more precisely, in Dornod and Sukhbaatar) took place
+# in Choibalsan (more precisely, in Dornod and Sükhbaatar) took place
 # at 02:00 standard time, not at 00:00 local time as in the rest of
 # the country.  That would be odd, and possibly is a result of their
 # correction of 02:00 (in the previous edition) not being done correctly
@@ -1822,13 +1934,13 @@ Rule	Mongol	2002	2006	-	Mar	lastSat	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # Hovd, a.k.a. Chovd, Dund-Us, Dzhargalant, Khovd, Jirgalanta
 Zone	Asia/Hovd	6:06:36 -	LMT	1905 Aug
-			6:00	-	HOVT	1978	# Hovd Time
+			6:00	-	HOVT	1978     # Hovd Time
 			7:00	Mongol	HOV%sT
 # Ulaanbaatar, a.k.a. Ulan Bataar, Ulan Bator, Urga
 Zone	Asia/Ulaanbaatar 7:07:32 -	LMT	1905 Aug
-			7:00	-	ULAT	1978	# Ulaanbaatar Time
+			7:00	-	ULAT	1978     # Ulaanbaatar Time
 			8:00	Mongol	ULA%sT
-# Choibalsan, a.k.a. Bajan Tuemen, Bajan Tumen, Chojbalsan,
+# Choibalsan, a.k.a. Bajan Tümen, Bajan Tumen, Chojbalsan,
 # Choybalsan, Sanbejse, Tchoibalsan
 Zone	Asia/Choibalsan	7:38:00 -	LMT	1905 Aug
 			7:00	-	ULAT	1978
@@ -1860,7 +1972,7 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 # 00:01 was to make it clear which day it was on.
 
 # From Paul Eggert (2002-03-15):
-# Jesper Norgaard found this URL:
+# Jesper Nørgaard found this URL:
 # http://www.pak.gov.pk/public/news/app/app06_dec.htm
 # (dated 2001-12-06) which says that the Cabinet adopted a scheme "to
 # advance the clocks by one hour on the night between the first
@@ -1892,43 +2004,30 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 # Here is an article that Pakistan plan to introduce Daylight Saving Time
 # on June 1, 2008 for 3 months.
 #
-# "... The federal cabinet on Wednesday announced a new conservation plan to help
-# reduce load shedding by approving the closure of commercial centres at 9pm and
-# moving clocks forward by one hour for the next three months.
-# ...."
+# "... The federal cabinet on Wednesday announced a new conservation plan to
+# help reduce load shedding by approving the closure of commercial centres at
+# 9pm and moving clocks forward by one hour for the next three months. ...."
 #
-# 
 # http://www.worldtimezone.net/dst_news/dst_news_pakistan01.html
-# 
-# OR
-# 
 # http://www.dailytimes.com.pk/default.asp?page=2008%5C05%5C15%5Cstory_15-5-2008_pg1_4
-# 
 
 # From Arthur David Olson (2008-05-19):
 # XXX--midnight transitions is a guess; 2008 only is a guess.
 
 # From Alexander Krivenyshev (2008-08-28):
 # Pakistan government has decided to keep the watches one-hour advanced
-# for another 2 months--plan to return to Standard Time on October 31
+# for another 2 months - plan to return to Standard Time on October 31
 # instead of August 31.
 #
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan02.html
-# 
-# OR
-# 
 # http://dailymailnews.com/200808/28/news/dmbrn03.html
-# 
 
 # From Alexander Krivenyshev (2009-04-08):
 # Based on previous media reports that "... proposed plan to
 # advance clocks by one hour from May 1 will cause disturbance
 # to the working schedules rather than bringing discipline in
 # official working."
-# 
 # http://www.thenews.com.pk/daily_detail.asp?id=171280
-# 
 #
 # recent news that instead of May 2009 - Pakistan plan to
 # introduce DST from April 15, 2009
@@ -1936,15 +2035,8 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 # FYI: Associated Press Of Pakistan
 # April 08, 2009
 # Cabinet okays proposal to advance clocks by one hour from April 15
-# 
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=73043&Itemid=1
-# 
-#
-# or
-#
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan05.html
-# 
 #
 # ....
 # The Federal Cabinet on Wednesday approved the proposal to
@@ -1957,34 +2049,20 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 # clocks backward by one hour from October 1. A formal announcement to
 # this effect will be made after the Prime Minister grants approval in
 # this regard."
-# 
 # http://www.thenews.com.pk/updates.asp?id=87168
-# 
 
 # From Alexander Krivenyshev (2009-09-28):
 # According to Associated Press Of Pakistan, it is confirmed that
-# Pakistan clocks across the country would be turned back by an hour from October
-# 1, 2009.
+# Pakistan clocks across the country would be turned back by an hour from
+# October 1, 2009.
 #
 # "Clocks to go back one hour from 1 Oct"
-# 
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm
-# 
-
-# From Steffen Thorsen (2009-09-29):
-# Alexander Krivenyshev wrote:
-# > According to Associated Press Of Pakistan, it is confirmed that
-# > Pakistan clocks across the country would be turned back by an hour from October
-# > 1, 2009.
 #
+# From Steffen Thorsen (2009-09-29):
 # Now they seem to have changed their mind, November 1 is the new date:
-# 
 # http://www.thenews.com.pk/top_story_detail.asp?Id=24742
-# 
 # "The country's clocks will be reversed by one hour on November 1.
 # Officials of Federal Ministry for Interior told this to Geo News on
 # Monday."
@@ -1996,11 +2074,9 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 #
 # We have confirmed this year's end date with both with the Ministry of
 # Water and Power and the Pakistan Electric Power Company:
-# 
 # http://www.timeanddate.com/news/time/pakistan-ends-dst09.html
-# 
 
-# From Christoph Goehre (2009-10-01):
+# From Christoph Göhre (2009-10-01):
 # [T]he German Consulate General in Karachi reported me today that Pakistan
 # will go back to standard time on 1st of November.
 
@@ -2016,22 +2092,17 @@ Zone	Asia/Muscat	3:54:24 -	LMT	1920
 # Now, it seems that the decision to not observe DST in final:
 #
 # "Govt Withdraws Plan To Advance Clocks"
-# 
 # http://www.apakistannews.com/govt-withdraws-plan-to-advance-clocks-172041
-# 
 #
 # "People laud PM's announcement to end DST"
-# 
 # http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=99374&Itemid=2
-# 
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule Pakistan	2002	only	-	Apr	Sun>=2	0:01	1:00	S
 Rule Pakistan	2002	only	-	Oct	Sun>=2	0:01	0	-
 Rule Pakistan	2008	only	-	Jun	1	0:00	1:00	S
-Rule Pakistan	2008	only	-	Nov	1	0:00	0	-
+Rule Pakistan	2008	2009	-	Nov	1	0:00	0	-
 Rule Pakistan	2009	only	-	Apr	15	0:00	1:00	S
-Rule Pakistan	2009	only	-	Nov	1	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Karachi	4:28:12 -	LMT	1907
@@ -2105,10 +2176,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # the PA has decided to implement DST in April.
 
 # From Paul Eggert (1999-09-20):
-# Daoud Kuttab writes in
-# 
-# Holiday havoc
-#  (Jerusalem Post, 1999-04-22) that
+# Daoud Kuttab writes in Holiday havoc
+# http://www.jpost.com/com/Archive/22.Apr.1999/Opinion/Article-2.html
+# (Jerusalem Post, 1999-04-22) that
 # the Palestinian National Authority changed to DST on 1999-04-15.
 # I vaguely recall that they switch back in October (sorry, forgot the source).
 # For now, let's assume that the spring switch was at 24:00,
@@ -2121,7 +2191,7 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # A user from Gaza reported that Gaza made the change early because of
 # the Ramadan.  Next year Ramadan will be even earlier, so I think
 # there is a good chance next year's end date will be around two weeks
-# earlier--the same goes for Jordan.
+# earlier - the same goes for Jordan.
 
 # From Steffen Thorsen (2006-08-17):
 # I was informed by a user in Bethlehem that in Bethlehem it started the
@@ -2140,7 +2210,7 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # I guess it is likely that next year's date will be moved as well,
 # because of the Ramadan.
 
-# From Jesper Norgaard Welen (2007-09-18):
+# From Jesper Nørgaard Welen (2007-09-18):
 # According to Steffen Thorsen's web site the Gaza Strip and the rest of the
 # Palestinian territories left DST early on 13.th. of September at 2:00.
 
@@ -2157,16 +2227,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # Gaza Strip (as Egypt) ended DST at midnight Thursday (Aug 28, 2008), while
 # the West Bank will end Daylight Saving Time at midnight Sunday (Aug 31, 2008).
 #
-# 
 # http://www.guardian.co.uk/world/feedarticle/7759001
-# 
-# 
 # http://www.abcnews.go.com/International/wireStory?id=5676087
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip01.html
-# 
 
 # From Alexander Krivenyshev (2009-03-26):
 # According to the Palestine News Network (arabic.pnn.ps), Palestinian
@@ -2174,24 +2237,17 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # 26 and continue until the night of 27 September 2009.
 #
 # (in Arabic)
-# 
 # http://arabic.pnn.ps/index.php?option=com_content&task=view&id=50850
-# 
 #
-# or
 # (English translation)
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_westbank01.html
-# 
 
 # From Steffen Thorsen (2009-08-31):
 # Palestine's Council of Ministers announced that they will revert back to
 # winter time on Friday, 2009-09-04.
 #
 # One news source:
-# 
 # http://www.safa.ps/ara/?action=showdetail&seid=4158
-# 
 # (Palestinian press agency, Arabic),
 # Google translate: "Decided that the Palestinian government in Ramallah
 # headed by Salam Fayyad, the start of work in time for the winter of
@@ -2200,9 +2256,7 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 #
 # We are not sure if Gaza will do the same, last year they had a different
 # end date, we will keep this page updated:
-# 
 # http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html
-# 
 
 # From Alexander Krivenyshev (2009-09-02):
 # Seems that Gaza Strip will go back to Winter Time same date as West Bank.
@@ -2212,51 +2266,35 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 #
 # "Winter time unite the West Bank and Gaza"
 # (from Palestinian National Authority):
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html
-# 
 
 # From Alexander Krivenyshev (2010-03-19):
 # According to Voice of Palestine DST will last for 191 days, from March
 # 26, 2010 till "the last Sunday before the tenth day of Tishri
 # (October), each year" (October 03, 2010?)
 #
-# 
 # http://palvoice.org/forums/showthread.php?t=245697
-# 
 # (in Arabic)
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_westbank03.html
-# 
 
 # From Steffen Thorsen (2010-03-24):
 # ...Ma'an News Agency reports that Hamas cabinet has decided it will
 # start one day later, at 12:01am. Not sure if they really mean 12:01am or
 # noon though:
 #
-# 
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=271178
-# 
 # (Ma'an News Agency)
 # "At 12:01am Friday, clocks in Israel and the West Bank will change to
 # 1:01am, while Gaza clocks will change at 12:01am Saturday morning."
 
 # From Steffen Thorsen (2010-08-11):
 # According to several sources, including
-# 
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=306795
-# 
 # the clocks were set back one hour at 2010-08-11 00:00:00 local time in
 # Gaza and the West Bank.
 # Some more background info:
-# 
 # http://www.timeanddate.com/news/time/westbank-gaza-end-dst-2010.html
-# 
 
 # From Steffen Thorsen (2011-08-26):
 # Gaza and the West Bank did go back to standard time in the beginning of
@@ -2264,13 +2302,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # 00:00 (so two periods of DST in 2011). The pause was because of
 # Ramadan.
 #
-# 
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=416217
-# 
 # Additional info:
-# 
 # http://www.timeanddate.com/news/time/palestine-dst-2011.html
-# 
 
 # From Alexander Krivenyshev (2011-08-27):
 # According to the article in The Jerusalem Post:
@@ -2280,14 +2314,9 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # The Hamas government said on Saturday that it won't observe summertime after
 # the Muslim feast of Id al-Fitr, which begins on Tuesday..."
 # ...
-# 
 # http://www.jpost.com/MiddleEast/Article.aspx?id=235650
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_gazastrip05.html
-# 
-# The rules for Egypt are stolen from the `africa' file.
+# The rules for Egypt are stolen from the 'africa' file.
 
 # From Steffen Thorsen (2011-09-30):
 # West Bank did end Daylight Saving Time this morning/midnight (2011-09-30
@@ -2295,26 +2324,18 @@ Zone	Asia/Karachi	4:28:12 -	LMT	1907
 # So West Bank and Gaza now have the same time again.
 #
 # Many sources, including:
-# 
 # http://www.maannews.net/eng/ViewDetails.aspx?ID=424808
-# 
 
 # From Steffen Thorsen (2012-03-26):
 # Palestinian news sources tell that both Gaza and West Bank will start DST
 # on Friday (Thursday midnight, 2012-03-29 24:00).
 # Some of many sources in Arabic:
-# 
 # http://www.samanews.com/index.php?act=Show&id=122638
-# 
 #
-# 
 # http://safa.ps/details/news/74352/%D8%A8%D8%AF%D8%A1-%D8%A7%D9%84%D8%AA%D9%88%D9%82%D9%8A%D8%AA-%D8%A7%D9%84%D8%B5%D9%8A%D9%81%D9%8A-%D8%A8%D8%A7%D9%84%D8%B6%D9%81%D8%A9-%D9%88%D8%BA%D8%B2%D8%A9-%D9%84%D9%8A%D9%84%D8%A9-%D8%A7%D9%84%D8%AC%D9%85%D8%B9%D8%A9.html
-# 
 #
 # Our brief summary:
-# 
 # http://www.timeanddate.com/news/time/gaza-west-bank-dst-2012.html
-# 
 
 # From Steffen Thorsen (2013-03-26):
 # The following news sources tells that Palestine will "start daylight saving
@@ -2374,10 +2395,10 @@ Zone	Asia/Gaza	2:17:52	-	LMT	1900 Oct
 			2:00 EgyptAsia	EE%sT	1967 Jun  5
 			2:00	Zion	I%sT	1996
 			2:00	Jordan	EE%sT	1999
-			2:00 Palestine	EE%sT	2008 Aug 29 0:00
+			2:00 Palestine	EE%sT	2008 Aug 29  0:00
 			2:00	-	EET	2008 Sep
 			2:00 Palestine	EE%sT	2010
-			2:00	-	EET	2010 Mar 27 0:01
+			2:00	-	EET	2010 Mar 27  0:01
 			2:00 Palestine	EE%sT	2011 Aug  1
 			2:00	-	EET	2012
 			2:00 Palestine	EE%sT
@@ -2393,25 +2414,27 @@ Zone	Asia/Hebron	2:20:23	-	LMT	1900 Oct
 # no information
 
 # Philippines
-# On 1844-08-16, Narciso Claveria, governor-general of the
+# On 1844-08-16, Narciso Clavería, governor-general of the
 # Philippines, issued a proclamation announcing that 1844-12-30 was to
-# be immediately followed by 1845-01-01.  Robert H. van Gent has a
-# transcript of the decree in .
-# The rest of the data are from Shanks & Pottenger.
+# be immediately followed by 1845-01-01; see R.H. van Gent's
+# History of the International Date Line
+# http://www.staff.science.uu.nl/~gent0113/idl/idl_philippines.htm
+# The rest of the data entries are from Shanks & Pottenger.
 
-# From Paul Eggert (2006-04-25):
-# Tomorrow's Manila Standard reports that the Philippines Department of
-# Trade and Industry is considering adopting DST this June when the
-# rainy season begins.  See
-# .
-# For now, we'll ignore this, since it's not definite and we lack details.
-#
-# From Jesper Norgaard Welen (2006-04-26):
+# From Jesper Nørgaard Welen (2006-04-26):
 # ... claims that Philippines had DST last time in 1990:
 # http://story.philippinetimes.com/p.x/ct/9/id/145be20cc6b121c0/cid/3e5bbccc730d258c/
 # [a story dated 2006-04-25 by Cris Larano of Dow Jones Newswires,
 # but no details]
 
+# From Paul Eggert (2014-08-14):
+# The following source says DST may be instituted November-January and again
+# March-June, but this is not definite.  It also says DST was last proclaimed
+# during the Ramos administration (1992-1998); but again, no details.
+# Carcamo D. PNoy urged to declare use of daylight saving time.
+# Philippine Star 2014-08-05
+# http://www.philstar.com/headlines/2014/08/05/1354152/pnoy-urged-declare-use-daylight-saving-time
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Phil	1936	only	-	Nov	1	0:00	1:00	S
 Rule	Phil	1937	only	-	Feb	1	0:00	0	-
@@ -2428,18 +2451,39 @@ Zone	Asia/Manila	-15:56:00 -	LMT	1844 Dec 31
 
 # Qatar
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Qatar	3:26:08 -	LMT	1920	# Al Dawhah / Doha
+Zone	Asia/Qatar	3:26:08 -	LMT	1920     # Al Dawhah / Doha
 			4:00	-	GST	1972 Jun
 			3:00	-	AST
 
 # Saudi Arabia
+#
+# From Paul Eggert (2014-07-15):
+# Time in Saudi Arabia and other countries in the Arabian peninsula was not
+# standardized until relatively recently; we don't know when, and possibly it
+# has never been made official.  Richard P Hunt, in "Islam city yielding to
+# modern times", New York Times (1961-04-09), p 20, wrote that only airlines
+# observed standard time, and that people in Jeddah mostly observed quasi-solar
+# time, doing so by setting their watches at sunrise to 6 o'clock (or to 12
+# o'clock for "Arab" time).
+#
+# The TZ database cannot represent quasi-solar time; airline time is the best
+# we can do.  The 1946 foreign air news digest of the U.S. Civil Aeronautics
+# Board (OCLC 42299995) reported that the "... Arabian Government, inaugurated
+# a weekly Dhahran-Cairo service, via the Saudi Arabian cities of Riyadh and
+# Jidda, on March 14, 1947".  Shanks & Pottenger guessed 1950; go with the
+# earlier date.
+#
+# Shanks & Pottenger also state that until 1968-05-01 Saudi Arabia had two
+# time zones; the other zone, at UTC+4, was in the far eastern part of
+# the country.  Ignore this, as it's before our 1970 cutoff.
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Riyadh	3:06:52 -	LMT	1950
+Zone	Asia/Riyadh	3:06:52 -	LMT	1947 Mar 14
 			3:00	-	AST
 
 # Singapore
-# The data here are taken from Mok Ly Yng (2003-10-30)
-# .
+# taken from Mok Ly Yng (2003-10-30)
+# http://www.math.nus.edu.sg/aslaksen/teaching/timezone.html
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 			6:55:25	-	SMT	1905 Jun  1 # Singapore M.T.
@@ -2465,26 +2509,24 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 
 # From Paul Eggert (1996-09-03):
 # "Sri Lanka advances clock by an hour to avoid blackout"
-# (www.virtual-pc.com/lankaweb/news/items/240596-2.html, 1996-05-24,
+# (, 1996-05-24,
 # no longer available as of 1999-08-17)
-# reported ``the country's standard time will be put forward by one hour at
-# midnight Friday (1830 GMT) `in the light of the present power crisis'.''
+# reported "the country's standard time will be put forward by one hour at
+# midnight Friday (1830 GMT) 'in the light of the present power crisis'."
 #
 # From Dharmasiri Senanayake, Sri Lanka Media Minister (1996-10-24), as quoted
-# by Shamindra in
-# 
-# Daily News - Hot News Section (1996-10-26)
-# :
+# by Shamindra in Daily News - Hot News Section
+#  (1996-10-26):
 # With effect from 12.30 a.m. on 26th October 1996
 # Sri Lanka will be six (06) hours ahead of GMT.
 
-# From Jesper Norgaard Welen (2006-04-14), quoting Sri Lanka News Online
+# From Jesper Nørgaard Welen (2006-04-14), quoting Sri Lanka News Online
 #  (2006-04-13):
 # 0030 hrs on April 15, 2006 (midnight of April 14, 2006 +30 minutes)
 # at present, become 2400 hours of April 14, 2006 (midnight of April 14, 2006).
 
 # From Peter Apps and Ranga Sirila of Reuters (2006-04-12) in:
-# 
+# http://today.reuters.co.uk/news/newsArticle.aspx?type=scienceNews&storyID=2006-04-12T172228Z_01_COL295762_RTRIDST_0_SCIENCE-SRILANKA-TIME-DC.XML
 # [The Tamil Tigers] never accepted the original 1996 time change and simply
 # kept their clocks set five and a half hours ahead of Greenwich Mean
 # Time (GMT), in line with neighbor India.
@@ -2498,7 +2540,7 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 # twice in 1996 and probably SL Government or its standardization
 # agencies never declared an abbreviation as a national standard.
 #
-# I recollect before the recent change the government annoucemments
+# I recollect before the recent change the government announcements
 # mentioning it as simply changing Sri Lanka Standard Time or Sri Lanka
 # Time and no mention was made about the abbreviation.
 #
@@ -2508,7 +2550,7 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 # item....
 #
 # Within Sri Lanka I think LKT is well known among computer users and
-# adminsitrators.  In my opinion SLT may not be a good choice because the
+# administrators.  In my opinion SLT may not be a good choice because the
 # nation's largest telcom / internet operator Sri Lanka Telcom is well
 # known by that abbreviation - simply as SLT (there IP domains are
 # slt.lk and sltnet.lk).
@@ -2523,13 +2565,13 @@ Zone	Asia/Singapore	6:55:25 -	LMT	1901 Jan  1
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Colombo	5:19:24 -	LMT	1880
-			5:19:32	-	MMT	1906	# Moratuwa Mean Time
+			5:19:32	-	MMT	1906        # Moratuwa Mean Time
 			5:30	-	IST	1942 Jan  5
 			5:30	0:30	IHST	1942 Sep
-			5:30	1:00	IST	1945 Oct 16 2:00
-			5:30	-	IST	1996 May 25 0:00
-			6:30	-	LKT	1996 Oct 26 0:30
-			6:00	-	LKT	2006 Apr 15 0:30
+			5:30	1:00	IST	1945 Oct 16  2:00
+			5:30	-	IST	1996 May 25  0:00
+			6:30	-	LKT	1996 Oct 26  0:30
+			6:00	-	LKT	2006 Apr 15  0:30
 			5:30	-	IST
 
 # Syria
@@ -2580,7 +2622,7 @@ Rule	Syria	2006	only	-	Sep	22	0:00	0	-
 # Today the AP reported "Syria will switch to summertime at midnight Thursday."
 # http://www.iht.com/articles/ap/2007/03/29/africa/ME-GEN-Syria-Time-Change.php
 Rule	Syria	2007	only	-	Mar	lastFri	0:00	1:00	S
-# From Jesper Norgard (2007-10-27):
+# From Jesper Nørgaard (2007-10-27):
 # The sister center ICARDA of my work CIMMYT is confirming that Syria DST will
 # not take place 1st November at 0:00 o'clock but 1st November at 24:00 or
 # rather Midnight between Thursday and Friday. This does make more sense than
@@ -2589,7 +2631,7 @@ Rule	Syria	2007	only	-	Mar	lastFri	0:00	1:00	S
 # it is implemented at midnight of the last workday before weekend...
 #
 # From Steffen Thorsen (2007-10-27):
-# Jesper Norgaard Welen wrote:
+# Jesper Nørgaard Welen wrote:
 #
 # > "Winter local time in Syria will be observed at midnight of Thursday 1
 # > November 2007, and the clock will be put back 1 hour."
@@ -2605,8 +2647,7 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
 
 # From Stephen Colebourne (2008-03-17):
 # For everyone's info, I saw an IATA time zone change for [Syria] for
-# this month (March 2008) in the last day or so...This is the data IATA
-# are now using:
+# this month (March 2008) in the last day or so....
 # Country     Time Standard   --- DST Start ---   --- DST End ---  DST
 # Name        Zone Variation   Time    Date        Time    Date
 # Variation
@@ -2618,16 +2659,15 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
 # From Arthur David Olson (2008-03-17):
 # Here's a link to English-language coverage by the Syrian Arab News
 # Agency (SANA)...
-# 
 # http://www.sana.sy/eng/21/2008/03/11/165173.htm
-# ...which reads (in part) "The Cabinet approved the suggestion of the
+# ...which reads (in part) "The Cabinet approved the suggestion of the
 # Ministry of Electricity to begin daylight savings time on Friday April
 # 4th, advancing clocks one hour ahead on midnight of Thursday April 3rd."
 # Since Syria is two hours east of UTC, the 2200 and 2100 transition times
 # shown above match up with midnight in Syria.
 
 # From Arthur David Olson (2008-03-18):
-# My buest guess at a Syrian rule is "the Friday nearest April 1";
+# My best guess at a Syrian rule is "the Friday nearest April 1";
 # coding that involves either using a "Mar Fri>=29" construct that old time zone
 # compilers can't handle  or having multiple Rules (a la Israel).
 # For now, use "Apr Fri>=1", and go with IATA on a uniform Sep 30 end.
@@ -2640,37 +2680,27 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
 # winter time on 2008-11-01 at 00:00 local daylight time (delaying/setting
 # clocks back 60 minutes).
 #
-# 
 # http://sana.sy/ara/2/2008/10/07/195459.htm
-# 
 
 # From Steffen Thorsen (2009-03-19):
 # Syria will start DST on 2009-03-27 00:00 this year according to many sources,
 # two examples:
 #
-# 
 # http://www.sana.sy/eng/21/2009/03/17/217563.htm
-# 
 # (English, Syrian Arab News # Agency)
-# 
 # http://thawra.alwehda.gov.sy/_View_news2.asp?FileName=94459258720090318012209
-# 
 # (Arabic, gov-site)
 #
 # We have not found any sources saying anything about when DST ends this year.
 #
 # Our summary
-# 
 # http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html
-# 
 
 # From Steffen Thorsen (2009-10-27):
 # The Syrian Arab News Network on 2009-09-29 reported that Syria will
 # revert back to winter (standard) time on midnight between Thursday
 # 2009-10-29 and Friday 2009-10-30:
-# 
 # http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic)
-# 
 
 # From Arthur David Olson (2009-10-28):
 # We'll see if future DST switching times turn out to be end of the last
@@ -2681,23 +2711,17 @@ Rule	Syria	2007	only	-	Nov	 Fri>=1	0:00	0	-
 # The "Syrian News Station" reported on 2010-03-16 that the Council of
 # Ministers has decided that Syria will start DST on midnight Thursday
 # 2010-04-01: (midnight between Thursday and Friday):
-# 
 # http://sns.sy/sns/?path=news/read/11421 (Arabic)
-# 
 
 # From Steffen Thorsen (2012-03-26):
 # Today, Syria's government announced that they will start DST early on Friday
 # (00:00). This is a bit earlier than the past two years.
 #
 # From Syrian Arab News Agency, in Arabic:
-# 
 # http://www.sana.sy/ara/2/2012/03/26/408215.htm
-# 
 #
 # Our brief summary:
-# 
 # http://www.timeanddate.com/news/time/syria-dst-2012.html
-# 
 
 # From Arthur David Olson (2012-03-27):
 # Assume last Friday in March going forward XXX.
@@ -2710,7 +2734,7 @@ Rule	Syria	2012	max	-	Mar	lastFri	0:00	1:00	S
 Rule	Syria	2009	max	-	Oct	lastFri	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Damascus	2:25:12 -	LMT	1920	# Dimashq
+Zone	Asia/Damascus	2:25:12 -	LMT	1920 # Dimashq
 			2:00	Syria	EE%sT
 
 # Tajikistan
@@ -2718,9 +2742,9 @@ Zone	Asia/Damascus	2:25:12 -	LMT	1920	# Dimashq
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Dushanbe	4:35:12 -	LMT	1924 May  2
 			5:00	-	DUST	1930 Jun 21 # Dushanbe Time
-			6:00 RussiaAsia DUS%sT	1991 Mar 31 2:00s
-			5:00	1:00	DUSST	1991 Sep  9 2:00s
-			5:00	-	TJT		    # Tajikistan Time
+			6:00 RussiaAsia DUS%sT	1991 Mar 31  2:00s
+			5:00	1:00	DUSST	1991 Sep  9  2:00s
+			5:00	-	TJT	# Tajikistan Time
 
 # Thailand
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -2733,9 +2757,9 @@ Zone	Asia/Bangkok	6:42:04	-	LMT	1880
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Ashgabat	3:53:32 -	LMT	1924 May  2 # or Ashkhabad
 			4:00	-	ASHT	1930 Jun 21 # Ashkhabad Time
-			5:00 RussiaAsia	ASH%sT	1991 Mar 31 2:00
+			5:00 RussiaAsia	ASH%sT	1991 Mar 31  2:00
 			4:00 RussiaAsia	ASH%sT	1991 Oct 27 # independence
-			4:00 RussiaAsia	TM%sT	1992 Jan 19 2:00
+			4:00 RussiaAsia	TM%sT	1992 Jan 19  2:00
 			5:00	-	TMT
 
 # United Arab Emirates
@@ -2744,8 +2768,9 @@ Zone	Asia/Dubai	3:41:12 -	LMT	1920
 			4:00	-	GST
 
 # Uzbekistan
+# Byalokoz 1919 says Uzbekistan was 4:27:53.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Asia/Samarkand	4:27:12 -	LMT	1924 May  2
+Zone	Asia/Samarkand	4:27:53 -	LMT	1924 May  2
 			4:00	-	SAMT	1930 Jun 21 # Samarkand Time
 			5:00	-	SAMT	1981 Apr  1
 			5:00	1:00	SAMST	1981 Oct  1
@@ -2753,9 +2778,10 @@ Zone	Asia/Samarkand	4:27:12 -	LMT	1924 May  2
 			5:00 RussiaAsia	SAM%sT	1991 Sep  1 # independence
 			5:00 RussiaAsia	UZ%sT	1992
 			5:00	-	UZT
-Zone	Asia/Tashkent	4:37:12 -	LMT	1924 May  2
+# Milne says Tashkent was 4:37:10.8; round to nearest.
+Zone	Asia/Tashkent	4:37:11 -	LMT	1924 May  2
 			5:00	-	TAST	1930 Jun 21 # Tashkent Time
-			6:00 RussiaAsia	TAS%sT	1991 Mar 31 2:00
+			6:00 RussiaAsia	TAS%sT	1991 Mar 31  2:00
 			5:00 RussiaAsia	TAS%sT	1991 Sep  1 # independence
 			5:00 RussiaAsia	UZ%sT	1992
 			5:00	-	UZT
@@ -2769,13 +2795,13 @@ Zone	Asia/Tashkent	4:37:12 -	LMT	1924 May  2
 # and Pottenger.
 
 # From Arthur David Olson (2008-03-18):
-# The English-language name of Vietnam's most populous city is "Ho Chi Min City";
-# we use Ho_Chi_Minh below to avoid a name of more than 14 characters.
+# The English-language name of Vietnam's most populous city is "Ho Chi Minh
+# City"; use Ho_Chi_Minh below to avoid a name of more than 14 characters.
 
 # From Shanks & Pottenger:
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Asia/Ho_Chi_Minh	7:06:40 -	LMT	1906 Jun  9
-			7:06:20	-	SMT	1911 Mar 11 0:01 # Saigon MT?
+			7:06:20	-	SMT	1911 Mar 11  0:01 # Saigon MT?
 			7:00	-	ICT	1912 May
 			8:00	-	ICT	1931 May
 			7:00	-	ICT
diff --git a/jdk/make/data/tzdata/australasia b/jdk/make/data/tzdata/australasia
index 94c9adb912c..52d32904178 100644
--- a/jdk/make/data/tzdata/australasia
+++ b/jdk/make/data/tzdata/australasia
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -36,13 +35,13 @@
 # Please see the notes below for the controversy about "EST" versus "AEST" etc.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	-
-Rule	Aus	1917	only	-	Mar	25	2:00	0	-
-Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	-
-Rule	Aus	1942	only	-	Mar	29	2:00	0	-
-Rule	Aus	1942	only	-	Sep	27	2:00	1:00	-
-Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	-
-Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	-
+Rule	Aus	1917	only	-	Jan	 1	0:01	1:00	D
+Rule	Aus	1917	only	-	Mar	25	2:00	0	S
+Rule	Aus	1942	only	-	Jan	 1	2:00	1:00	D
+Rule	Aus	1942	only	-	Mar	29	2:00	0	S
+Rule	Aus	1942	only	-	Sep	27	2:00	1:00	D
+Rule	Aus	1943	1944	-	Mar	lastSun	2:00	0	S
+Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	D
 # Go with Whitman and the Australian National Standards Commission, which
 # says W Australia didn't use DST in 1943/1944.  Ignore Whitman's claim that
 # 1944/1945 was just like 1943/1944.
@@ -50,26 +49,26 @@ Rule	Aus	1943	only	-	Oct	 3	2:00	1:00	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # Northern Territory
 Zone Australia/Darwin	 8:43:20 -	LMT	1895 Feb
-			 9:00	-	CST	1899 May
-			 9:30	Aus	CST
+			 9:00	-	ACST	1899 May
+			 9:30	Aus	AC%sT
 # Western Australia
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	1991	only	-	Nov	17	2:00s	1:00	-
-Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	-
-Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	-
-Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	-
-Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	-
+Rule	AW	1974	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AW	1975	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	1983	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AW	1984	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	1991	only	-	Nov	17	2:00s	1:00	D
+Rule	AW	1992	only	-	Mar	Sun>=1	2:00s	0	S
+Rule	AW	2006	only	-	Dec	 3	2:00s	1:00	D
+Rule	AW	2007	2009	-	Mar	lastSun	2:00s	0	S
+Rule	AW	2007	2008	-	Oct	lastSun	2:00s	1:00	D
 Zone Australia/Perth	 7:43:24 -	LMT	1895 Dec
-			 8:00	Aus	WST	1943 Jul
-			 8:00	AW	WST
+			 8:00	Aus	AW%sT	1943 Jul
+			 8:00	AW	AW%sT
 Zone Australia/Eucla	 8:35:28 -	LMT	1895 Dec
-			 8:45	Aus	CWST	1943 Jul
-			 8:45	AW	CWST
+			 8:45	Aus	ACW%sT	1943 Jul
+			 8:45	AW	ACW%sT
 
 # Queensland
 #
@@ -85,150 +84,150 @@ Zone Australia/Eucla	 8:35:28 -	LMT	1895 Dec
 # so use Lindeman.
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	-
-Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	-
-Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	-
-Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	-
-Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	-
+Rule	AQ	1971	only	-	Oct	lastSun	2:00s	1:00	D
+Rule	AQ	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AQ	1989	1991	-	Oct	lastSun	2:00s	1:00	D
+Rule	AQ	1990	1992	-	Mar	Sun>=1	2:00s	0	S
+Rule	Holiday	1992	1993	-	Oct	lastSun	2:00s	1:00	D
+Rule	Holiday	1993	1994	-	Mar	Sun>=1	2:00s	0	S
 Zone Australia/Brisbane	10:12:08 -	LMT	1895
-			10:00	Aus	EST	1971
-			10:00	AQ	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AQ	AE%sT
 Zone Australia/Lindeman  9:55:56 -	LMT	1895
-			10:00	Aus	EST	1971
-			10:00	AQ	EST	1992 Jul
-			10:00	Holiday	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AQ	AE%sT	1992 Jul
+			10:00	Holiday	AE%sT
 
 # South Australia
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AS	1986	only	-	Oct	19	2:00s	1:00	-
-Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AS	1972	only	-	Feb	27	2:00s	0	-
-Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AS	1991	only	-	Mar	3	2:00s	0	-
-Rule	AS	1992	only	-	Mar	22	2:00s	0	-
-Rule	AS	1993	only	-	Mar	7	2:00s	0	-
-Rule	AS	1994	only	-	Mar	20	2:00s	0	-
-Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AS	2006	only	-	Apr	2	2:00s	0	-
-Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AS	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AS	1986	only	-	Oct	19	2:00s	1:00	D
+Rule	AS	1987	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AS	1972	only	-	Feb	27	2:00s	0	S
+Rule	AS	1973	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AS	1986	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AS	1991	only	-	Mar	3	2:00s	0	S
+Rule	AS	1992	only	-	Mar	22	2:00s	0	S
+Rule	AS	1993	only	-	Mar	7	2:00s	0	S
+Rule	AS	1994	only	-	Mar	20	2:00s	0	S
+Rule	AS	1995	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AS	2006	only	-	Apr	2	2:00s	0	S
+Rule	AS	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AS	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AS	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Adelaide	9:14:20 -	LMT	1895 Feb
-			9:00	-	CST	1899 May
-			9:30	Aus	CST	1971
-			9:30	AS	CST
+			9:00	-	ACST	1899 May
+			9:30	Aus	AC%sT	1971
+			9:30	AS	AC%sT
 
 # Tasmania
 #
 # From Paul Eggert (2005-08-16):
-# 
+# http://www.bom.gov.au/climate/averages/tables/dst_times.shtml
 # says King Island didn't observe DST from WWII until late 1971.
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	-
-Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	-
-Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	-
-Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	-
-Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	-
-Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	-
-Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	-
-Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	-
-Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	-
-Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	-
+Rule	AT	1967	only	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	1968	only	-	Mar	lastSun	2:00s	0	S
+Rule	AT	1968	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AT	1969	1971	-	Mar	Sun>=8	2:00s	0	S
+Rule	AT	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AT	1973	1981	-	Mar	Sun>=1	2:00s	0	S
+Rule	AT	1982	1983	-	Mar	lastSun	2:00s	0	S
+Rule	AT	1984	1986	-	Mar	Sun>=1	2:00s	0	S
+Rule	AT	1986	only	-	Oct	Sun>=15	2:00s	1:00	D
+Rule	AT	1987	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AT	1987	only	-	Oct	Sun>=22	2:00s	1:00	D
+Rule	AT	1988	1990	-	Oct	lastSun	2:00s	1:00	D
+Rule	AT	1991	1999	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	1991	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AT	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AT	2001	max	-	Oct	Sun>=1	2:00s	1:00	D
+Rule	AT	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AT	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AT	2008	max	-	Apr	Sun>=1	2:00s	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Hobart	9:49:16	-	LMT	1895 Sep
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1967
-			10:00	AT	EST
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1967
+			10:00	AT	AE%sT
 Zone Australia/Currie	9:35:28	-	LMT	1895 Sep
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1971 Jul
-			10:00	AT	EST
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1971 Jul
+			10:00	AT	AE%sT
 
 # Victoria
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	-
-Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	-
-Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	-
-Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	-
-Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AV	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	1972	only	-	Feb	lastSun	2:00s	0	S
+Rule	AV	1973	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AV	1986	1990	-	Mar	Sun>=15	2:00s	0	S
+Rule	AV	1986	1987	-	Oct	Sun>=15	2:00s	1:00	D
+Rule	AV	1988	1999	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	1991	1994	-	Mar	Sun>=1	2:00s	0	S
+Rule	AV	1995	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AV	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AV	2001	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AV	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AV	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AV	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AV	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Melbourne 9:39:52 -	LMT	1895 Feb
-			10:00	Aus	EST	1971
-			10:00	AV	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AV	AE%sT
 
 # New South Wales
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	1972	only	-	Feb	27	2:00s	0	-
-Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	-
-Rule	AN	1986	only	-	Oct	19	2:00s	1:00	-
-Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	-
-Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	-
-Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	-
-Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	-
-Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	-
-Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	-
-Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	-
+Rule	AN	1971	1985	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	1972	only	-	Feb	27	2:00s	0	S
+Rule	AN	1973	1981	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1982	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	1983	1985	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1986	1989	-	Mar	Sun>=15	2:00s	0	S
+Rule	AN	1986	only	-	Oct	19	2:00s	1:00	D
+Rule	AN	1987	1999	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	1990	1995	-	Mar	Sun>=1	2:00s	0	S
+Rule	AN	1996	2005	-	Mar	lastSun	2:00s	0	S
+Rule	AN	2000	only	-	Aug	lastSun	2:00s	1:00	D
+Rule	AN	2001	2007	-	Oct	lastSun	2:00s	1:00	D
+Rule	AN	2006	only	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	2007	only	-	Mar	lastSun	2:00s	0	S
+Rule	AN	2008	max	-	Apr	Sun>=1	2:00s	0	S
+Rule	AN	2008	max	-	Oct	Sun>=1	2:00s	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Australia/Sydney	10:04:52 -	LMT	1895 Feb
-			10:00	Aus	EST	1971
-			10:00	AN	EST
+			10:00	Aus	AE%sT	1971
+			10:00	AN	AE%sT
 Zone Australia/Broken_Hill 9:25:48 -	LMT	1895 Feb
-			10:00	-	EST	1896 Aug 23
-			9:00	-	CST	1899 May
-			9:30	Aus	CST	1971
-			9:30	AN	CST	2000
-			9:30	AS	CST
+			10:00	-	AEST	1896 Aug 23
+			9:00	-	ACST	1899 May
+			9:30	Aus	AC%sT	1971
+			9:30	AN	AC%sT	2000
+			9:30	AS	AC%sT
 
 # Lord Howe Island
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	-
-Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	-
-Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	-
-Rule	LH	1986	only	-	Oct	19	2:00	0:30	-
-Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	-
-Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	-
-Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	-
-Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	-
-Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	-
-Rule	LH	2007	only	-	Mar	lastSun	2:00	0	-
-Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	-
-Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	-
+Rule	LH	1981	1984	-	Oct	lastSun	2:00	1:00	D
+Rule	LH	1982	1985	-	Mar	Sun>=1	2:00	0	S
+Rule	LH	1985	only	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	1986	1989	-	Mar	Sun>=15	2:00	0	S
+Rule	LH	1986	only	-	Oct	19	2:00	0:30	D
+Rule	LH	1987	1999	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	1990	1995	-	Mar	Sun>=1	2:00	0	S
+Rule	LH	1996	2005	-	Mar	lastSun	2:00	0	S
+Rule	LH	2000	only	-	Aug	lastSun	2:00	0:30	D
+Rule	LH	2001	2007	-	Oct	lastSun	2:00	0:30	D
+Rule	LH	2006	only	-	Apr	Sun>=1	2:00	0	S
+Rule	LH	2007	only	-	Mar	lastSun	2:00	0	S
+Rule	LH	2008	max	-	Apr	Sun>=1	2:00	0	S
+Rule	LH	2008	max	-	Oct	Sun>=1	2:00	0:30	D
 Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
-			10:00	-	EST	1981 Mar
-			10:30	LH	LHST
+			10:00	-	AEST	1981 Mar
+			10:30	LH	LH%sT
 
 # Australian miscellany
 #
@@ -244,8 +243,8 @@ Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
 # Permanent occupation (scientific station) 1911-1915 and since 25 March 1948;
 # sealing and penguin oil station operated Nov 1899 to Apr 1919.  See the
 # Tasmania Parks & Wildlife Service history of sealing at Macquarie Island
-# 
-# .
+# http://www.parks.tas.gov.au/index.aspx?base=1828
+# http://www.parks.tas.gov.au/index.aspx?base=1831
 # Guess that it was like Australia/Hobart while inhabited before 2010.
 #
 # From Steffen Thorsen (2010-03-10):
@@ -256,16 +255,16 @@ Zone Australia/Lord_Howe 10:36:20 -	LMT	1895 Feb
 #
 # From Arthur David Olson (2013-05-23):
 # The 1919 transition is overspecified below so pre-2013 zics
-# will produce a binary file with an EST-type as the first 32-bit type;
+# will produce a binary file with an [A]EST-type as the first 32-bit type;
 # this is required for correct handling of times before 1916 by
 # pre-2013 versions of localtime.
 Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
-			10:00	-	EST	1916 Oct 1 2:00
-			10:00	1:00	EST	1917 Feb
-			10:00	Aus	EST	1919 Apr 1 0:00s
+			10:00	-	AEST	1916 Oct  1  2:00
+			10:00	1:00	AEDT	1917 Feb
+			10:00	Aus	AE%sT	1919 Apr  1  0:00s
 			0	-	zzz	1948 Mar 25
-			10:00	Aus	EST	1967
-			10:00	AT	EST	2010 Apr 4 3:00
+			10:00	Aus	AE%sT	1967
+			10:00	AT	AE%sT	2010 Apr  4  3:00
 			11:00	-	MIST	# Macquarie I Standard Time
 
 # Christmas
@@ -273,24 +272,14 @@ Zone Antarctica/Macquarie 0	-	zzz	1899 Nov
 Zone Indian/Christmas	7:02:52 -	LMT	1895 Feb
 			7:00	-	CXT	# Christmas Island Time
 
-# Cook Is
-# From Shanks & Pottenger:
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
-Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
-Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
-# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901		# Avarua
-			-10:30	-	CKT	1978 Nov 12	# Cook Is Time
-			-10:00	Cook	CK%sT
-
-# Cocos
+# Cocos (Keeling) Is
 # These islands were ruled by the Ross family from about 1830 to 1978.
 # We don't know when standard time was introduced; for now, we guess 1900.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Indian/Cocos	6:27:40	-	LMT	1900
 			6:30	-	CCT	# Cocos Islands Time
 
+
 # Fiji
 
 # Milne gives 11:55:44 for Suva.
@@ -300,20 +289,13 @@ Zone	Indian/Cocos	6:27:40	-	LMT	1900
 # from November 29th 2009  to April 25th 2010.
 #
 # "Daylight savings to commence this month"
-# 
 # http://www.radiofiji.com.fj/fullstory.php?id=23719
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_fiji01.html
-# 
 
 # From Steffen Thorsen (2009-11-10):
 # The Fiji Government has posted some more details about the approved
 # amendments:
-# 
 # http://www.fiji.gov.fj/publish/page_16198.shtml
-# 
 
 # From Steffen Thorsen (2010-03-03):
 # The Cabinet in Fiji has decided to end DST about a month early, on
@@ -322,35 +304,24 @@ Zone	Indian/Cocos	6:27:40	-	LMT	1900
 # 2011 (last Sunday a good guess?).
 #
 # Official source:
-# 
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=1096:3310-cabinet-approves-change-in-daylight-savings-dates&catid=49:cabinet-releases&Itemid=166
-# 
 #
 # A bit more background info here:
-# 
 # http://www.timeanddate.com/news/time/fiji-dst-ends-march-2010.html
-# 
 
 # From Alexander Krivenyshev (2010-10-24):
 # According to Radio Fiji and Fiji Times online, Fiji will end DST 3
 # weeks earlier than expected - on March 6, 2011, not March 27, 2011...
 # Here is confirmation from Government of the Republic of the Fiji Islands,
 # Ministry of Information (fiji.gov.fj) web site:
-# 
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=2608:daylight-savings&catid=71:press-releases&Itemid=155
-# 
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_fiji04.html
-# 
 
 # From Steffen Thorsen (2011-10-03):
 # Now the dates have been confirmed, and at least our start date
 # assumption was correct (end date was one week wrong).
 #
-# 
-# www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
-# 
+# http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=4966:daylight-saving-starts-in-fiji&catid=71:press-releases&Itemid=155
 # which says
 # Members of the public are reminded to change their time to one hour in
 # advance at 2am to 3am on October 23, 2011 and one hour back at 3am to
@@ -360,9 +331,7 @@ Zone	Indian/Cocos	6:27:40	-	LMT	1900
 # Another change to the Fiji DST end date. In the TZ database the end date for
 # Fiji DST 2012, is currently Feb 26. This has been changed to Jan 22.
 #
-# 
 # http://www.fiji.gov.fj/index.php?option=com_content&view=article&id=5017:amendments-to-daylight-savings&catid=71:press-releases&Itemid=155
-# 
 # states:
 #
 # The end of daylight saving scheduled initially for the 26th of February 2012
@@ -400,16 +369,16 @@ Rule	Fiji	2011	only	-	Mar	Sun>=1	3:00	0	-
 Rule	Fiji	2012	2013	-	Jan	Sun>=18	3:00	0	-
 Rule	Fiji	2014	max	-	Jan	Sun>=18	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26	# Suva
+Zone	Pacific/Fiji	11:55:44 -	LMT	1915 Oct 26 # Suva
 			12:00	Fiji	FJ%sT	# Fiji Time
 
 # French Polynesia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct	# Rikitea
+Zone	Pacific/Gambier	 -8:59:48 -	LMT	1912 Oct # Rikitea
 			 -9:00	-	GAMT	# Gambier Time
 Zone	Pacific/Marquesas -9:18:00 -	LMT	1912 Oct
 			 -9:30	-	MART	# Marquesas Time
-Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct	# Papeete
+Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct # Papeete
 			-10:00	-	TAHT	# Tahiti Time
 # Clipperton (near North America) is administered from French Polynesia;
 # it is uninhabited.
@@ -417,14 +386,14 @@ Zone	Pacific/Tahiti	 -9:58:16 -	LMT	1912 Oct	# Papeete
 # Guam
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Guam	-14:21:00 -	LMT	1844 Dec 31
-			 9:39:00 -	LMT	1901		# Agana
-			10:00	-	GST	2000 Dec 23	# Guam
+			 9:39:00 -	LMT	1901        # Agana
+			10:00	-	GST	2000 Dec 23 # Guam
 			10:00	-	ChST	# Chamorro Standard Time
 
 # Kiribati
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Tarawa	 11:32:04 -	LMT	1901		# Bairiki
-			 12:00	-	GILT		 # Gilbert Is Time
+Zone Pacific/Tarawa	 11:32:04 -	LMT	1901 # Bairiki
+			 12:00	-	GILT	# Gilbert Is Time
 Zone Pacific/Enderbury	-11:24:20 -	LMT	1901
 			-12:00	-	PHOT	1979 Oct # Phoenix Is Time
 			-11:00	-	PHOT	1995
@@ -438,7 +407,7 @@ Zone Pacific/Kiritimati	-10:29:20 -	LMT	1901
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Saipan	-14:17:00 -	LMT	1844 Dec 31
 			 9:43:00 -	LMT	1901
-			 9:00	-	MPT	1969 Oct # N Mariana Is Time
+			 9:00	-	MPT	1969 Oct    # N Mariana Is Time
 			10:00	-	MPT	2000 Dec 23
 			10:00	-	ChST	# Chamorro Standard Time
 
@@ -449,24 +418,24 @@ Zone Pacific/Majuro	11:24:48 -	LMT	1901
 			12:00	-	MHT
 Zone Pacific/Kwajalein	11:09:20 -	LMT	1901
 			11:00	-	MHT	1969 Oct
-			-12:00	-	KWAT	1993 Aug 20	# Kwajalein Time
+			-12:00	-	KWAT	1993 Aug 20 # Kwajalein Time
 			12:00	-	MHT
 
 # Micronesia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Chuuk	10:07:08 -	LMT	1901
-			10:00	-	CHUT			# Chuuk Time
-Zone Pacific/Pohnpei	10:32:52 -	LMT	1901		# Kolonia
-			11:00	-	PONT			# Pohnpei Time
+			10:00	-	CHUT	# Chuuk Time
+Zone Pacific/Pohnpei	10:32:52 -	LMT	1901 # Kolonia
+			11:00	-	PONT	# Pohnpei Time
 Zone Pacific/Kosrae	10:51:56 -	LMT	1901
-			11:00	-	KOST	1969 Oct	# Kosrae Time
+			11:00	-	KOST	1969 Oct # Kosrae Time
 			12:00	-	KOST	1999
 			11:00	-	KOST
 
 # Nauru
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15	# Uaobe
-			11:30	-	NRT	1942 Mar 15	# Nauru Time
+Zone	Pacific/Nauru	11:07:40 -	LMT	1921 Jan 15 # Uaobe
+			11:30	-	NRT	1942 Mar 15 # Nauru Time
 			9:00	-	JST	1944 Aug 15
 			11:30	-	NRT	1979 May
 			12:00	-	NRT
@@ -479,7 +448,7 @@ Rule	NC	1996	only	-	Dec	 1	2:00s	1:00	S
 # Shanks & Pottenger say the following was at 2:00; go with IATA.
 Rule	NC	1997	only	-	Mar	 2	2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13
+Zone	Pacific/Noumea	11:05:48 -	LMT	1912 Jan 13 # Nouméa
 			11:00	NC	NC%sT
 
 
@@ -496,7 +465,8 @@ Rule	NZ	1934	1940	-	Apr	lastSun	2:00	0	M
 Rule	NZ	1934	1940	-	Sep	lastSun	2:00	0:30	S
 Rule	NZ	1946	only	-	Jan	 1	0:00	0	S
 # Since 1957 Chatham has been 45 minutes ahead of NZ, but there's no
-# convenient notation for this so we must duplicate the Rule lines.
+# convenient single notation for the date and time of this transition
+# so we must duplicate the Rule lines.
 Rule	NZ	1974	only	-	Nov	Sun>=1	2:00s	1:00	D
 Rule	Chatham	1974	only	-	Nov	Sun>=1	2:45s	1:00	D
 Rule	NZ	1975	only	-	Feb	lastSun	2:00s	0	S
@@ -519,13 +489,14 @@ Rule	Chatham	2008	max	-	Apr	Sun>=1	2:45s	0	S
 Zone Pacific/Auckland	11:39:04 -	LMT	1868 Nov  2
 			11:30	NZ	NZ%sT	1946 Jan  1
 			12:00	NZ	NZ%sT
-Zone Pacific/Chatham	12:13:48 -	LMT	1957 Jan  1
+Zone Pacific/Chatham	12:13:48 -	LMT	1868 Nov  2
+			12:15	-	CHAST	1946 Jan  1
 			12:45	Chatham	CHA%sT
 
 Link Pacific/Auckland Antarctica/McMurdo
 
 # Auckland Is
-# uninhabited; Maori and Moriori, colonial settlers, pastoralists, sealers,
+# uninhabited; Māori and Moriori, colonial settlers, pastoralists, sealers,
 # and scientific personnel have wintered
 
 # Campbell I
@@ -534,48 +505,58 @@ Link Pacific/Auckland Antarctica/McMurdo
 # previously whalers, sealers, pastoralists, and scientific personnel wintered
 # was probably like Pacific/Auckland
 
+# Cook Is
+# From Shanks & Pottenger:
+# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	Cook	1978	only	-	Nov	12	0:00	0:30	HS
+Rule	Cook	1979	1991	-	Mar	Sun>=1	0:00	0	-
+Rule	Cook	1979	1990	-	Oct	lastSun	0:00	0:30	HS
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Zone Pacific/Rarotonga	-10:39:04 -	LMT	1901        # Avarua
+			-10:30	-	CKT	1978 Nov 12 # Cook Is Time
+			-10:00	Cook	CK%sT
+
 ###############################################################################
 
 
 # Niue
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Niue	-11:19:40 -	LMT	1901		# Alofi
-			-11:20	-	NUT	1951	# Niue Time
-			-11:30	-	NUT	1978 Oct 1
+Zone	Pacific/Niue	-11:19:40 -	LMT	1901        # Alofi
+			-11:20	-	NUT	1951        # Niue Time
+			-11:30	-	NUT	1978 Oct  1
 			-11:00	-	NUT
 
 # Norfolk
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Norfolk	11:11:52 -	LMT	1901		# Kingston
-			11:12	-	NMT	1951	# Norfolk Mean Time
-			11:30	-	NFT		# Norfolk Time
+Zone	Pacific/Norfolk	11:11:52 -	LMT	1901 # Kingston
+			11:12	-	NMT	1951 # Norfolk Mean Time
+			11:30	-	NFT	# Norfolk Time
 
 # Palau (Belau)
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Palau	8:57:56 -	LMT	1901		# Koror
+Zone Pacific/Palau	8:57:56 -	LMT	1901 # Koror
 			9:00	-	PWT	# Palau Time
 
 # Papua New Guinea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Port_Moresby 9:48:40 -	LMT	1880
-			9:48:32	-	PMMT	1895	# Port Moresby Mean Time
-			10:00	-	PGT		# Papua New Guinea Time
+			9:48:32	-	PMMT	1895 # Port Moresby Mean Time
+			10:00	-	PGT	# Papua New Guinea Time
 
 # Pitcairn
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901		# Adamstown
-			-8:30	-	PNT	1998 Apr 27 00:00
+Zone Pacific/Pitcairn	-8:40:20 -	LMT	1901        # Adamstown
+			-8:30	-	PNT	1998 Apr 27  0:00
 			-8:00	-	PST	# Pitcairn Standard Time
 
 # American Samoa
 Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
 			-11:22:48 -	LMT	1911
-			-11:30	-	SAMT	1950		# Samoa Time
-			-11:00	-	NST	1967 Apr	# N=Nome
-			-11:00	-	BST	1983 Nov 30	# B=Bering
-			-11:00	-	SST			# S=Samoa
+			-11:00	-	NST	1967 Apr    # N=Nome
+			-11:00	-	BST	1983 Nov 30 # B=Bering
+			-11:00	-	SST	            # S=Samoa
 
-# Samoa
+# Samoa (formerly and also known as Western Samoa)
 
 # From Steffen Thorsen (2009-10-16):
 # We have been in contact with the government of Samoa again, and received
@@ -586,141 +567,80 @@ Zone Pacific/Pago_Pago	 12:37:12 -	LMT	1879 Jul  5
 # Sunday of April 2011."
 #
 # Background info:
-# 
 # http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html
-# 
 #
 # Samoa's Daylight Saving Time Act 2009 is available here, but does not
 # contain any dates:
-# 
 # http://www.parliament.gov.ws/documents/acts/Daylight%20Saving%20Act%20%202009%20%28English%29%20-%20Final%207-7-091.pdf
-# 
 
 # From Laupue Raymond Hughes (2010-10-07):
 # Please see
-# 
 # http://www.mcil.gov.ws
-# ,
 # the Ministry of Commerce, Industry and Labour (sideframe) "Last Sunday
 # September 2010 (26/09/10) - adjust clocks forward from 12:00 midnight
 # to 01:00am and First Sunday April 2011 (03/04/11) - adjust clocks
 # backwards from 1:00am to 12:00am"
 
 # From Laupue Raymond Hughes (2011-03-07):
-# I believe this will be posted shortly on the website
-# 
-# www.mcil.gov.ws
-# 
+# [http://www.mcil.gov.ws/ftcd/daylight_saving_2011.pdf]
 #
-# PUBLIC NOTICE ON DAYLIGHT SAVING TIME
-#
-# Pursuant to the Daylight Saving Act 2009 and Cabinets decision,
-# businesses and the general public are hereby advised that daylight
-# saving time is on the first Saturday of April 2011 (02/04/11).
-#
-# The public is therefore advised that when the standard time strikes
-# the hour of four oclock (4.00am or 0400 Hours) on the 2nd April 2011,
-# then all instruments used to measure standard time are to be
-# adjusted/changed to three oclock (3:00am or 0300Hrs).
-#
-# Margaret Fruean ACTING CHIEF EXECUTIVE OFFICER MINISTRY OF COMMERCE,
-# INDUSTRY AND LABOUR 28th February 2011
+# ... when the standard time strikes the hour of four o'clock (4.00am
+# or 0400 Hours) on the 2nd April 2011, then all instruments used to
+# measure standard time are to be adjusted/changed to three o'clock
+# (3:00am or 0300Hrs).
 
-# From David Zuelke (2011-05-09):
+# From David Zülke (2011-05-09):
 # Subject: Samoa to move timezone from east to west of international date line
 #
-# 
 # http://www.morningstar.co.uk/uk/markets/newsfeeditem.aspx?id=138501958347963
-# 
 
-# From Mark Sim-Smith (2011-08-17):
-# I have been in contact with Leilani Tuala Warren from the Samoa Law
-# Reform Commission, and she has sent me a copy of the Bill that she
-# confirmed has been passed...Most of the sections are about maps rather
-# than the time zone change, but I'll paste the relevant bits below. But
-# the essence is that at midnight 29 Dec (UTC-11 I suppose), Samoa
-# changes from UTC-11 to UTC+13:
-#
-# International Date Line Bill 2011
-#
-# AN ACT to provide for the change to standard time in Samoa and to make
-# consequential amendments to the position of the International Date
-# Line, and for related purposes.
-#
-# BE IT ENACTED by the Legislative Assembly of Samoa in Parliament
-# assembled as follows:
-#
-# 1. Short title and commencement-(1) This Act may be cited as the
-# International Date Line Act 2011. (2) Except for section 5(3) this Act
-# commences at 12 o'clock midnight, on Thursday 29th December 2011. (3)
-# Section 5(3) commences on the date of assent by the Head of State.
-#
-# [snip]
-#
-# 3. Interpretation - [snip] "Samoa standard time" in this Act and any
-# other statute of Samoa which refers to 'Samoa standard time' means the
-# time 13 hours in advance of Co-ordinated Universal Time.
-#
-# 4. Samoa standard time - (1) Upon the commencement of this Act, Samoa
-# standard time shall be set at 13 hours in advance of Co-ordinated
-# Universal Time for the whole of Samoa. (2) All references to Samoa's
-# time zone and to Samoa standard time in Samoa in all legislation and
-# instruments after the commencement of this Act shall be references to
-# Samoa standard time as provided for in this Act. (3) Nothing in this
-# Act affects the provisions of the Daylight Saving Act 2009, except that
-# it defines Samoa standard time....
+# From Paul Eggert (2014-06-27):
+# The International Date Line Act 2011
+# http://www.parliament.gov.ws/images/ACTS/International_Date_Line_Act__2011_-_Eng.pdf
+# changed Samoa from UTC-11 to UTC+13, effective "12 o'clock midnight, on
+# Thursday 29th December 2011".  The International Date Line was adjusted
+# accordingly.
 
 # From Laupue Raymond Hughes (2011-09-02):
-# 
 # http://www.mcil.gov.ws/mcil_publications.html
-# 
 #
 # here is the official website publication for Samoa DST and dateline change
 #
 # DST
-# Year	End	Time	Start	Time
-# 2011	- - -	- - -	24 September	3:00am to 4:00am
-# 2012	01 April	4:00am to 3:00am	- - -	- - -
+# Year  End      Time              Start        Time
+# 2011  - - -    - - -             24 September 3:00am to 4:00am
+# 2012  01 April 4:00am to 3:00am  - - -        - - -
 #
 # Dateline Change skip Friday 30th Dec 2011
 # Thursday 29th December 2011	23:59:59 Hours
 # Saturday 31st December 2011	00:00:00 Hours
 #
-# Clarification by Tim Parenti (2012-01-03):
-# Although Samoa has used Daylight Saving Time in the 2010-2011 and 2011-2012
-# seasons, there is not yet any indication that this trend will continue on
-# a regular basis. For now, we have explicitly listed the transitions below.
-#
-# From Nicky (2012-09-10):
+# From Nicholas Pereira (2012-09-10):
 # Daylight Saving Time commences on Sunday 30th September 2012 and
-# ends on Sunday 7th of April 2013.
-#
-# Please find link below for more information.
+# ends on Sunday 7th of April 2013....
 # http://www.mcil.gov.ws/mcil_publications.html
 #
-# That publication also includes dates for Summer of 2013/4 as well
-# which give the impression of a pattern in selecting dates for the
-# future, so for now, we will guess this will continue.
+# From Paul Eggert (2014-07-08):
+# That web page currently lists transitions for 2012/3 and 2013/4.
+# Assume the pattern instituted in 2012 will continue indefinitely.
 
-# Western Samoa
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
+Rule	WS	2010	only	-	Sep	lastSun	0:00	1	D
+Rule	WS	2011	only	-	Apr	Sat>=1	4:00	0	S
+Rule	WS	2011	only	-	Sep	lastSat	3:00	1	D
+Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	S
 Rule	WS	2012	max	-	Sep	lastSun	3:00	1	D
-Rule	WS	2012	max	-	Apr	Sun>=1	4:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Pacific/Apia	 12:33:04 -	LMT	1879 Jul  5
 			-11:26:56 -	LMT	1911
-			-11:30	-	SAMT	1950		# Samoa Time
-			-11:00	-	WST	2010 Sep 26
-			-11:00	1:00	WSDT	2011 Apr 2 4:00
-			-11:00	-	WST	2011 Sep 24 3:00
-			-11:00	1:00	WSDT	2011 Dec 30
-			 13:00	1:00	WSDT	2012 Apr Sun>=1 4:00
+			-11:30	-	WSST	1950
+			-11:00	WS	S%sT	2011 Dec 29 24:00 # S=Samoa
 			 13:00	WS	WS%sT
 
 # Solomon Is
 # excludes Bougainville, for which see Papua New Guinea
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct	# Honiara
+Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct # Honiara
 			11:00	-	SBT	# Solomon Is Time
 
 # Tokelau Is
@@ -744,7 +664,7 @@ Zone Pacific/Guadalcanal 10:39:48 -	LMT	1912 Oct	# Honiara
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Pacific/Fakaofo	-11:24:56 -	LMT	1901
-			-11:00	-	TKT 2011 Dec 30	# Tokelau Time
+			-11:00	-	TKT	2011 Dec 30 # Tokelau Time
 			13:00	-	TKT
 
 # Tonga
@@ -804,8 +724,8 @@ Zone Pacific/Funafuti	11:56:52 -	LMT	1901
 # time from Operation Newsreel (Hardtack I/Teak shot, 1958-08-01) to the last
 # Operation Fishbowl shot (Tightrope, 1962-11-04).... [See] Herman Hoerlin,
 # "The United States High-Altitude Test Experience: A Review Emphasizing the
-# Impact on the Environment", Los Alamos LA-6405, Oct 1976
-# .
+# Impact on the Environment", Los Alamos LA-6405, Oct 1976.
+# http://www.fas.org/sgp/othergov/doe/lanl/docs1/00322994.pdf
 # See the table on page 4 where he lists GMT and local times for the tests; a
 # footnote for the JI tests reads that local time is "JI time = Hawaii Time
 # Minus One Hour".
@@ -820,7 +740,7 @@ Zone Pacific/Funafuti	11:56:52 -	LMT	1901
 # From Mark Brader (2005-01-23):
 # [Fallacies and Fantasies of Air Transport History, by R.E.G. Davies,
 # published 1994 by Paladwr Press, McLean, VA, USA; ISBN 0-9626483-5-3]
-# reproduced a Pan American Airways timeables from 1936, for their weekly
+# reproduced a Pan American Airways timetable from 1936, for their weekly
 # "Orient Express" flights between San Francisco and Manila, and connecting
 # flights to Chicago and the US East Coast.  As it uses some time zone
 # designations that I've never seen before:....
@@ -830,9 +750,9 @@ Zone Pacific/Funafuti	11:56:52 -	LMT	1901
 Zone Pacific/Midway	-11:49:28 -	LMT	1901
 			-11:00	-	NST	1956 Jun  3
 			-11:00	1:00	NDT	1956 Sep  2
-			-11:00	-	NST	1967 Apr	# N=Nome
-			-11:00	-	BST	1983 Nov 30	# B=Bering
-			-11:00	-	SST			# S=Samoa
+			-11:00	-	NST	1967 Apr    # N=Nome
+			-11:00	-	BST	1983 Nov 30 # B=Bering
+			-11:00	-	SST	            # S=Samoa
 
 # Palmyra
 # uninhabited since World War II; was probably like Pacific/Kiritimati
@@ -852,7 +772,7 @@ Rule	Vanuatu	1985	1991	-	Sep	Sun>=23	0:00	1:00	S
 Rule	Vanuatu	1992	1993	-	Jan	Sun>=23	0:00	0	-
 Rule	Vanuatu	1992	only	-	Oct	Sun>=23	0:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13		# Vila
+Zone	Pacific/Efate	11:13:16 -	LMT	1912 Jan 13 # Vila
 			11:00	Vanuatu	VU%sT	# Vanuatu Time
 
 # Wallis and Futuna
@@ -864,9 +784,10 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 
 # NOTES
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2013-02-21):
 # A good source for time zone historical data outside the U.S. is
@@ -887,165 +808,188 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # I found in the UCLA library.
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# .
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # A reliable and entertaining source about time zones is
 # Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
 #
-# I invented the abbreviations marked `*' in the following table;
+# I invented the abbreviations marked '*' in the following table;
 # the rest are from earlier versions of this file, or from other sources.
 # Corrections are welcome!
-#		std dst
-#		LMT	Local Mean Time
-#	  8:00	WST WST	Western Australia
-#	  8:45	CWST CWST Central Western Australia*
-#	  9:00	JST	Japan
-#	  9:30	CST CST	Central Australia
-#	 10:00	EST EST	Eastern Australia
-#	 10:00	ChST	Chamorro
-#	 10:30	LHST LHST Lord Howe*
-#	 11:30	NZMT NZST New Zealand through 1945
-#	 12:00	NZST NZDT New Zealand 1946-present
-#	 12:45	CHAST CHADT Chatham*
-#	-11:00	SST	Samoa
-#	-10:00	HST	Hawaii
-#	- 8:00	PST	Pitcairn*
+#		std	dst
+#		LMT		Local Mean Time
+#	  8:00	AWST	AWDT	Western Australia
+#	  8:45	ACWST	ACWDT	Central Western Australia*
+#	  9:00	JST		Japan
+#	  9:30	ACST	ACDT	Central Australia
+#	 10:00	AEST	AEDT	Eastern Australia
+#	 10:00	ChST		Chamorro
+#	 10:30	LHST	LHDT	Lord Howe*
+#	 11:30	NZMT	NZST	New Zealand through 1945
+#	 12:00	NZST	NZDT	New Zealand 1946-present
+#	 12:15	CHAST		Chatham through 1945*
+#	 12:45	CHAST	CHADT	Chatham 1946-present*
+#	 13:00	WSST	WSDT	(western) Samoa 2011-present*
+#	-11:30	WSST		Western Samoa through 1950*
+#	-11:00	SST		Samoa
+#	-10:00	HST		Hawaii
+#	- 8:00	PST		Pitcairn*
 #
-# See the `northamerica' file for Hawaii.
-# See the `southamerica' file for Easter I and the Galapagos Is.
+# See the 'northamerica' file for Hawaii.
+# See the 'southamerica' file for Easter I and the Galápagos Is.
 
 ###############################################################################
 
 # Australia
 
+# From Paul Eggert (2014-06-30):
+# Daylight saving time has long been controversial in Australia, pitting
+# region against region, rural against urban, and local against global.
+# For example, in her review of Graeme Davison's _The Unforgiving
+# Minute: how Australians learned to tell the time_ (1993), Perth native
+# Phillipa J Martyr wrote, "The section entitled 'Saving Daylight' was
+# very informative, but was (as can, sadly, only be expected from a
+# Melbourne-based study) replete with the usual chuckleheaded
+# Queenslanders and straw-chewing yokels from the West prattling fables
+# about fading curtains and crazed farm animals."
+# Electronic Journal of Australian and New Zealand History (1997-03-03)
+# http://www.jcu.edu.au/aff/history/reviews/davison.htm
+
 # From Paul Eggert (2005-12-08):
-# 
 # Implementation Dates of Daylight Saving Time within Australia
-#  summarizes daylight saving issues in Australia.
+# http://www.bom.gov.au/climate/averages/tables/dst_times.shtml
+# summarizes daylight saving issues in Australia.
 
 # From Arthur David Olson (2005-12-12):
-# 
 # Lawlink NSW:Daylight Saving in New South Wales
-#  covers New South Wales in particular.
+# http://www.lawlink.nsw.gov.au/lawlink/Corporate/ll_agdinfo.nsf/pages/community_relations_daylight_saving
+# covers New South Wales in particular.
 
 # From John Mackin (1991-03-06):
-# We in Australia have _never_ referred to DST as `daylight' time.
-# It is called `summer' time.  Now by a happy coincidence, `summer'
-# and `standard' happen to start with the same letter; hence, the
+# We in Australia have _never_ referred to DST as 'daylight' time.
+# It is called 'summer' time.  Now by a happy coincidence, 'summer'
+# and 'standard' happen to start with the same letter; hence, the
 # abbreviation does _not_ change...
 # The legislation does not actually define abbreviations, at least
 # in this State, but the abbreviation is just commonly taken to be the
 # initials of the phrase, and the legislation here uniformly uses
-# the phrase `summer time' and does not use the phrase `daylight
+# the phrase 'summer time' and does not use the phrase 'daylight
 # time'.
 # Announcers on the Commonwealth radio network, the ABC (for Australian
-# Broadcasting Commission), use the phrases `Eastern Standard Time'
-# or `Eastern Summer Time'.  (Note, though, that as I say in the
+# Broadcasting Commission), use the phrases 'Eastern Standard Time'
+# or 'Eastern Summer Time'.  (Note, though, that as I say in the
 # current australasia file, there is really no such thing.)  Announcers
 # on its overseas service, Radio Australia, use the same phrases
-# prefixed by the word `Australian' when referring to local times;
+# prefixed by the word 'Australian' when referring to local times;
 # time announcements on that service, naturally enough, are made in UTC.
 
-# From Arthur David Olson (1992-03-08):
-# Given the above, what's chosen for year-round use is:
-#	CST	for any place operating at a GMTOFF of 9:30
-#	WST	for any place operating at a GMTOFF of 8:00
-#	EST	for any place operating at a GMTOFF of 10:00
-
-# From Chuck Soper (2006-06-01):
-# I recently found this Australian government web page on time zones:
-# 
-# And this government web page lists time zone names and abbreviations:
-# 
-
-# From Paul Eggert (2001-04-05), summarizing a long discussion about "EST"
-# versus "AEST" etc.:
+# From Paul Eggert (2014-06-30):
 #
-# I see the following points of dispute:
+# Inspired by Mackin's remarks quoted above, earlier versions of this
+# file used "EST" for both Eastern Standard Time and Eastern Summer
+# Time in Australia, and similarly for "CST", "CWST", and "WST".
+# However, these abbreviations were confusing and were not common
+# practice among Australians, and there were justifiable complaints
+# about them, so I attempted to survey current Australian usage.
+# For the tz database, the full English phrase is not that important;
+# what matters is the abbreviation.  It's difficult to survey the web
+# directly for abbreviation usage, as there are so many false hits for
+# strings like "EST" and "EDT", so I looked for pages that defined an
+# abbreviation for eastern or central DST in Australia, and got the
+# following numbers of unique hits for the listed Google queries:
 #
-# * How important are unique time zone abbreviations?
+#   10 "Eastern Daylight Time AEST" site:au [some are false hits]
+#   10 "Eastern Summer Time AEST" site:au
+#   10 "Summer Time AEDT" site:au
+#   13 "EDST Eastern Daylight Saving Time" site:au
+#   18 "Summer Time ESST" site:au
+#   28 "Eastern Daylight Saving Time EDST" site:au
+#   39 "EDT Eastern Daylight Time" site:au [some are false hits]
+#   53 "Eastern Daylight Time EDT" site:au [some are false hits]
+#   54 "AEDT Australian Eastern Daylight Time" site:au
+#  182 "Eastern Daylight Time AEDT" site:au
 #
-#   Here I tend to agree with the point (most recently made by Chris
-#   Newman) that unique abbreviations should not be essential for proper
-#   operation of software.  We have other instances of ambiguity
-#   (e.g. "IST" denoting both "Israel Standard Time" and "Indian
-#   Standard Time"), and they are not likely to go away any time soon.
-#   In the old days, some software mistakenly relied on unique
-#   abbreviations, but this is becoming less true with time, and I don't
-#   think it's that important to cater to such software these days.
+#   17 "Central Daylight Time CDT" site:au [some are false hits]
+#   46 "Central Daylight Time ACDT" site:au
 #
-#   On the other hand, there is another motivation for unambiguous
-#   abbreviations: it cuts down on human confusion.  This is
-#   particularly true for Australia, where "EST" can mean one thing for
-#   time T and a different thing for time T plus 1 second.
+# I tried several other variants (e.g., "Eastern Summer Time EST") but
+# they all returned fewer than 10 unique hits.  I also looked for pages
+# mentioning both "western standard time" and an abbreviation, since
+# there is no WST in the US to generate false hits, and found:
 #
-# * Does the relevant legislation indicate which abbreviations should be used?
+#  156 "western standard time" AWST site:au
+#  226 "western standard time" WST site:au
 #
-#   Here I tend to think that things are a mess, just as they are in
-#   many other countries.  We Americans are currently disagreeing about
-#   which abbreviation to use for the newly legislated Chamorro Standard
-#   Time, for example.
+# I then surveyed the top ten newspapers in Australia by circulation as
+# listed in Wikipedia, using Google queries like "AEDT site:heraldsun.com.au"
+# and obtaining estimated counts from the initial page of search results.
+# All ten papers greatly preferred "AEDT" to "EDT".  The papers
+# surveyed were the Herald Sun, The Daily Telegraph, The Courier-Mail,
+# The Sydney Morning Herald, The West Australian, The Age, The Advertiser,
+# The Australian, The Financial Review, and The Herald (Newcastle).
 #
-#   Personally, I would prefer to use common practice; I would like to
-#   refer to legislation only for examples of common practice, or as a
-#   tiebreaker.
+# I also searched for historical usage, to see whether abbreviations
+# like "AEDT" are new.  A Trove search 
+# found only one newspaper (The Canberra Times) with a house style
+# dating back to the 1970s, I expect because other newspapers weren't
+# fully indexed.  The Canberra Times strongly preferred abbreviations
+# like "AEDT".  The first occurrence of "AEDT" was a World Weather
+# column (1971-11-17, page 24), and of "ACDT" was a Scoreboard column
+# (1993-01-24, p 16).  The style was the typical usage but was not
+# strictly enforced; for example, "Welcome to the twilight zones ..."
+# (1994-10-29, p 1) uses the abbreviations AEST/AEDT, CST/CDT, and
+# WST, and goes on to say, "The confusion and frustration some feel
+# about the lack of uniformity among Australia's six states and two
+# territories has prompted one group to form its very own political
+# party -- the Sydney-based Daylight Saving Extension Party."
 #
-# * Do Australians more often use "Eastern Daylight Time" or "Eastern
-#   Summer Time"?  Do they typically prefix the time zone names with
-#   the word "Australian"?
+# I also surveyed federal government sources.  They did not agree:
 #
-#   My own impression is that both "Daylight Time" and "Summer Time" are
-#   common and are widely understood, but that "Summer Time" is more
-#   popular; and that the leading "A" is also common but is omitted more
-#   often than not.  I just used AltaVista advanced search and got the
-#   following count of page hits:
+#   The Australian Government (2014-03-26)
+#   http://australia.gov.au/about-australia/our-country/time
+#   (This document was produced by the Department of Finance.)
+#   AEST ACST AWST AEDT ACDT
 #
-#     1,103 "Eastern Summer Time" AND domain:au
-#       971 "Australian Eastern Summer Time" AND domain:au
-#       613 "Eastern Daylight Time" AND domain:au
-#       127 "Australian Eastern Daylight Time" AND domain:au
+#   Bureau of Meteorology (2012-11-08)
+#   http://www.bom.gov.au/climate/averages/tables/daysavtm.shtml
+#   EST CST WST EDT CDT
 #
-#   Here "Summer" seems quite a bit more popular than "Daylight",
-#   particularly when we know the time zone is Australian and not US,
-#   say.  The "Australian" prefix seems to be popular for Eastern Summer
-#   Time, but unpopular for Eastern Daylight Time.
+#   Civil Aviation Safety Authority (undated)
+#   http://services.casa.gov.au/outnback/inc/pages/episode3/episode-3_time_zones.shtml
+#   EST CST WST (no abbreviations given for DST)
 #
-#   For abbreviations, tools like AltaVista are less useful because of
-#   ambiguity.  Many hits are not really time zones, unfortunately, and
-#   many hits denote US time zones and not Australian ones.  But here
-#   are the hit counts anyway:
+#   Geoscience Australia (2011-11-24)
+#   http://www.ga.gov.au/geodesy/astro/sunrise.jsp
+#   AEST ACST AWST AEDT ACDT
 #
-#     161,304 "EST" and domain:au
-#      25,156 "EDT" and domain:au
-#      18,263 "AEST" and domain:au
-#      10,416 "AEDT" and domain:au
+#   Parliamentary Library (2008-11-10)
+#   http://www.aph.gov.au/binaries/library/pubs/rp/2008-09/09rp14.pdf
+#   EST CST WST preferred for standard time; AEST AEDT ACST ACDT also used
 #
-#      14,538 "CST" and domain:au
-#       5,728 "CDT" and domain:au
-#         176 "ACST" and domain:au
-#          29 "ACDT" and domain:au
+#   The Transport Safety Bureau has an extensive series of accident reports,
+#   and investigators seem to use whatever abbreviation they like.
+#   Googling site:atsb.gov.au found the following number of unique hits:
+#   311 "ESuT", 195 "EDT", 26 "AEDT", 83 "CSuT", 46 "CDT".
+#   "_SuT" tended to appear in older reports, and "A_DT" tended to
+#   appear in reports of events with international implications.
 #
-#       7,539 "WST" and domain:au
-#          68 "AWST" and domain:au
-#
-#   This data suggest that Australians tend to omit the "A" prefix in
-#   practice.  The situation for "ST" versus "DT" is less clear, given
-#   the ambiguities involved.
-#
-# * How do Australians feel about the abbreviations in the tz database?
-#
-#   If you just count Australians on this list, I count 2 in favor and 3
-#   against.  One of the "against" votes (David Keegel) counseled delay,
-#   saying that both AEST/AEDT and EST/EST are widely used and
-#   understood in Australia.
+# From the above it appears that there is a working consensus in
+# Australia to use trailing "DT" for daylight saving time; although
+# some sources use trailing "SST" or "ST" or "SuT" they are by far in
+# the minority.  The case for leading "A" is weaker, but since it
+# seems to be preferred in the overall web and is preferred in all
+# the leading newspaper websites and in many government departments,
+# it has a stronger case than omitting the leading "A".  The current
+# version of the database therefore uses abbreviations like "AEST" and
+# "AEDT" for Australian time zones.
 
 # From Paul Eggert (1995-12-19):
 # Shanks & Pottenger report 2:00 for all autumn changes in Australia and NZ.
 # Mark Prior writes that his newspaper
 # reports that NSW's fall 1995 change will occur at 2:00,
 # but Robert Elz says it's been 3:00 in Victoria since 1970
-# and perhaps the newspaper's `2:00' is referring to standard time.
+# and perhaps the newspaper's '2:00' is referring to standard time.
 # For now we'll continue to assume 2:00s for changes since 1960.
 
 # From Eric Ulevik (1998-01-05):
@@ -1055,17 +999,14 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # relevant entries in this database.
 #
 # NSW (including LHI and Broken Hill):
-# 
 # Standard Time Act 1987 (updated 1995-04-04)
-# 
+# http://www.austlii.edu.au/au/legis/nsw/consol_act/sta1987137/index.html
 # ACT
-# 
 # Standard Time and Summer Time Act 1972
-# 
+# http://www.austlii.edu.au/au/legis/act/consol_act/stasta1972279/index.html
 # SA
-# 
 # Standard Time Act, 1898
-# 
+# http://www.austlii.edu.au/au/legis/sa/consol_act/sta1898137/index.html
 
 # From David Grosz (2005-06-13):
 # It was announced last week that Daylight Saving would be extended by
@@ -1083,7 +1024,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # Victoria: I wasn't able to find anything separate, but the other articles
 # allude to it.
 # But not Queensland
-# http://www.news.com.au/story/0,10117,15564030-1248,00.html.
+# http://www.news.com.au/story/0,10117,15564030-1248,00.html
 
 # Northern Territory
 
@@ -1130,9 +1071,9 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # The 1992 ending date used in the rules is a best guess;
 # it matches what was used in the past.
 
-# 
 # The Australian Bureau of Meteorology FAQ
-#  (1999-09-27) writes that Giles Meteorological Station uses
+# http://www.bom.gov.au/faq/faqgen.htm
+# (1999-09-27) writes that Giles Meteorological Station uses
 # South Australian time even though it's located in Western Australia.
 
 # Queensland
@@ -1173,9 +1114,9 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # The chosen rules the union of the 1971/1972 change and the 1989-1992 changes.
 
 # From Christopher Hunt (2006-11-21), after an advance warning
-# from Jesper Norgaard Welen (2006-11-01):
+# from Jesper Nørgaard Welen (2006-11-01):
 # WA are trialing DST for three years.
-# 
+# http://www.parliament.wa.gov.au/parliament/bills.nsf/9A1B183144403DA54825721200088DF1/$File/Bill175-1B.pdf
 
 # From Rives McDow (2002-04-09):
 # The most interesting region I have found consists of three towns on the
@@ -1189,7 +1130,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # From Paul Eggert (2002-04-09):
 # This is confirmed by the section entitled
 # "What's the deal with time zones???" in
-# .
+# http://www.earthsci.unimelb.edu.au/~awatkins/null.html
 #
 # From Alex Livingston (2006-12-07):
 # ... it was just on four years ago that I drove along the Eyre Highway,
@@ -1337,7 +1278,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # Based on law library research by John Mackin,
 # who notes:
 #	In Australia, time is not legislated federally, but rather by the
-#	individual states.  Thus, while such terms as ``Eastern Standard Time''
+#	individual states.  Thus, while such terms as "Eastern Standard Time"
 #	[I mean, of course, Australian EST, not any other kind] are in common
 #	use, _they have NO REAL MEANING_, as they are not defined in the
 #	legislation.  This is very important to understand.
@@ -1345,48 +1286,42 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 
 # From Eric Ulevik (1999-05-26):
 # DST will start in NSW on the last Sunday of August, rather than the usual
-# October in 2000.  [See: Matthew Moore,
-# 
-# Two months more daylight saving
-# 
-# Sydney Morning Herald (1999-05-26).]
+# October in 2000.  See: Matthew Moore,
+# Two months more daylight saving, Sydney Morning Herald (1999-05-26).
+# http://www.smh.com.au/news/9905/26/pageone/pageone4.html
 
 # From Paul Eggert (1999-09-27):
 # See the following official NSW source:
-# 
 # Daylight Saving in New South Wales.
-# 
+# http://dir.gis.nsw.gov.au/cgi-bin/genobject/document/other/daylightsaving/tigGmZ
 #
 # Narrabri Shire (NSW) council has announced it will ignore the extension of
 # daylight saving next year.  See:
-# 
 # Narrabri Council to ignore daylight saving
-#  (1999-07-22).  For now, we'll wait to see if this really happens.
+# http://abc.net.au/news/regionals/neweng/monthly/regeng-22jul1999-1.htm
+# (1999-07-22).  For now, we'll wait to see if this really happens.
 #
 # Victoria will following NSW.  See:
-# 
-# Vic to extend daylight saving
-#  (1999-07-28).
+# Vic to extend daylight saving (1999-07-28)
+# http://abc.net.au/local/news/olympics/1999/07/item19990728112314_1.htm
 #
 # However, South Australia rejected the DST request.  See:
-# 
-# South Australia rejects Olympics daylight savings request
-#  (1999-07-19).
+# South Australia rejects Olympics daylight savings request (1999-07-19)
+# http://abc.net.au/news/olympics/1999/07/item19990719151754_1.htm
 #
 # Queensland also will not observe DST for the Olympics.  See:
-# 
 # Qld says no to daylight savings for Olympics
-#  (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
-# ``Look you've got to remember in my family when this came up last time
+# http://abc.net.au/news/olympics/1999/06/item19990601114608_1.htm
+# (1999-06-01), which quotes Queensland Premier Peter Beattie as saying
+# "Look you've got to remember in my family when this came up last time
 # I voted for it, my wife voted against it and she said to me it's all very
 # well for you, you don't have to worry about getting the children out of
 # bed, getting them to school, getting them to sleep at night.
-# I've been through all this argument domestically...my wife rules.''
+# I've been through all this argument domestically...my wife rules."
 #
 # Broken Hill will stick with South Australian time in 2000.  See:
-# 
-# Broken Hill to be behind the times
-#  (1999-07-21).
+# Broken Hill to be behind the times (1999-07-21)
+# http://abc.net.au/news/regionals/brokenh/monthly/regbrok-21jul1999-6.htm
 
 # IATA SSIM (1998-09) says that the spring 2000 change for Australian
 # Capital Territory, New South Wales except Lord Howe Island and Broken
@@ -1402,7 +1337,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # Yancowinna
 
 # From John Mackin (1989-01-04):
-# `Broken Hill' means the County of Yancowinna.
+# 'Broken Hill' means the County of Yancowinna.
 
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
 # # YANCOWINNA..  [ Confirmation courtesy of Broken Hill Postmaster ]
@@ -1459,9 +1394,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # summer (southern hemisphere).
 #
 # From
-# 
 # http://www.safework.sa.gov.au/uploaded_files/DaylightDatesSet.pdf
-# 
 # The extended daylight saving period that South Australia has been trialling
 # for over the last year is now set to be ongoing.
 # Daylight saving will continue to start on the first Sunday in October each
@@ -1471,9 +1404,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # the ACT for all 52 weeks of the year...
 #
 # We have a wrap-up here:
-# 
 # http://www.timeanddate.com/news/time/south-australia-extends-dst.html
-# 
 ###############################################################################
 
 # New Zealand
@@ -1482,7 +1413,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # the 1989/90 year was a trial of an extended "daylight saving" period.
 # This trial was deemed successful and the extended period adopted for
 # subsequent years (with the addition of a further week at the start).
-# source -- phone call to Ministry of Internal Affairs Head Office.
+# source - phone call to Ministry of Internal Affairs Head Office.
 
 # From George Shepherd via Simon Woodhead via Robert Elz (1991-03-06):
 # # The Country of New Zealand   (Australia's east island -) Gee they hate that!
@@ -1524,6 +1455,19 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # that DST will begin on 2007-09-30 2008-04-06.
 # http://www.dia.govt.nz/diawebsite.nsf/wpg_URL/Services-Daylight-Saving-Daylight-saving-to-be-extended
 
+# From Paul Eggert (2014-07-14):
+# Chatham Island time was formally standardized on 1957-01-01 by
+# New Zealand's Standard Time Amendment Act 1956 (1956-10-26).
+# http://www.austlii.edu.au/nz/legis/hist_act/staa19561956n100244.pdf
+# According to Google Books snippet view, a speaker in the New Zealand
+# parliamentary debates in 1956 said "Clause 78 makes provision for standard
+# time in the Chatham Islands.  The time there is 45 minutes in advance of New
+# Zealand time.  I understand that is the time they keep locally, anyhow."
+# For now, assume this practice goes back to the introduction of standard time
+# in New Zealand, as this would make Chatham Islands time almost exactly match
+# LMT back when New Zealand was at UTC+11:30; also, assume Chatham Islands did
+# not observe New Zealand's prewar DST.
+
 ###############################################################################
 
 
@@ -1543,7 +1487,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 
 # From the BBC World Service in
 # http://news.bbc.co.uk/2/hi/asia-pacific/205226.stm (1998-10-31 16:03 UTC):
-# The Fijiian government says the main reasons for the time change is to
+# The Fijian government says the main reasons for the time change is to
 # improve productivity and reduce road accidents.... [T]he move is also
 # intended to boost Fiji's ability to attract tourists to witness the dawning
 # of the new millennium.
@@ -1551,16 +1495,12 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # http://www.fiji.gov.fj/press/2000_09/2000_09_13-05.shtml (2000-09-13)
 # reports that Fiji has discontinued DST.
 
-# Johnston
-
-# Johnston data is from usno1995.
-
 
 # Kiribati
 
 # From Paul Eggert (1996-01-22):
 # Today's _Wall Street Journal_ (page 1) reports that Kiribati
-# ``declared it the same day [throughout] the country as of Jan. 1, 1995''
+# "declared it the same day [throughout] the country as of Jan. 1, 1995"
 # as part of the competition to be first into the 21st century.
 
 
@@ -1575,8 +1515,8 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 
 # N Mariana Is, Guam
 
-# Howse writes (p 153) ``The Spaniards, on the other hand, reached the
-# Philippines and the Ladrones from America,'' and implies that the Ladrones
+# Howse writes (p 153) "The Spaniards, on the other hand, reached the
+# Philippines and the Ladrones from America," and implies that the Ladrones
 # (now called the Marianas) kept American date for quite some time.
 # For now, we assume the Ladrones switched at the same time as the Philippines;
 # see Asia/Manila.
@@ -1590,17 +1530,16 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # Micronesia
 
 # Alan Eugene Davis writes (1996-03-16),
-# ``I am certain, having lived there for the past decade, that "Truk"
-# (now properly known as Chuuk) ... is in the time zone GMT+10.''
+# "I am certain, having lived there for the past decade, that 'Truk'
+# (now properly known as Chuuk) ... is in the time zone GMT+10."
 #
 # Shanks & Pottenger write that Truk switched from UTC+10 to UTC+11
 # on 1978-10-01; ignore this for now.
 
 # From Paul Eggert (1999-10-29):
 # The Federated States of Micronesia Visitors Board writes in
-# 
-# The Federated States of Micronesia - Visitor Information
-#  (1999-01-26)
+# The Federated States of Micronesia - Visitor Information (1999-01-26)
+# http://www.fsmgov.org/info/clocks.html
 # that Truk and Yap are UTC+10, and Ponape and Kosrae are UTC+11.
 # We don't know when Kosrae switched from UTC+12; assume January 1 for now.
 
@@ -1646,27 +1585,34 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # Sacramento but it was changed a couple of years ago.
 
 
-# Samoa
+# (Western) Samoa and American Samoa
 
 # Howse writes (p 153, citing p 10 of the 1883-11-18 New York Herald)
 # that in 1879 the King of Samoa decided to change
-# ``the date in his kingdom from the Antipodean to the American system,
-# ordaining -- by a masterpiece of diplomatic flattery -- that
-# the Fourth of July should be celebrated twice in that year.''
+# "the date in his kingdom from the Antipodean to the American system,
+# ordaining - by a masterpiece of diplomatic flattery - that
+# the Fourth of July should be celebrated twice in that year."
 
+# Although Shanks & Pottenger says they both switched to UTC-11:30
+# in 1911, and to UTC-11 in 1950. many earlier sources give UTC-11
+# for American Samoa, e.g., the US National Bureau of Standards
+# circular "Standard Time Throughout the World", 1932.
+# Assume American Samoa switched to UTC-11 in 1911, not 1950,
+# and that after 1950 they agreed until (western) Samoa skipped a
+# day in 2011.  Assume also that the Samoas follow the US and New
+# Zealand's "ST"/"DT" style of daylight-saving abbreviations.
 
 # Tonga
 
 # From Paul Eggert (1996-01-22):
-# Today's _Wall Street Journal_ (p 1) reports that ``Tonga has been plotting
-# to sneak ahead of [New Zealanders] by introducing daylight-saving time.''
+# Today's _Wall Street Journal_ (p 1) reports that "Tonga has been plotting
+# to sneak ahead of [New Zealanders] by introducing daylight-saving time."
 # Since Kiribati has moved the Date Line it's not clear what Tonga will do.
 
 # Don Mundell writes in the 1997-02-20 Tonga Chronicle
-# 
-# How Tonga became `The Land where Time Begins'
-# :
-
+# How Tonga became 'The Land where Time Begins':
+# http://www.tongatapu.net.to/tonga/homeland/timebegins.htm
+#
 # Until 1941 Tonga maintained a standard time 50 minutes ahead of NZST
 # 12 hours and 20 minutes ahead of GMT.  When New Zealand adjusted its
 # standard time in 1940s, Tonga had the choice of subtracting from its
@@ -1674,8 +1620,8 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # advancing its time to maintain the differential of 13 degrees
 # (approximately 50 minutes ahead of New Zealand time).
 #
-# Because His Majesty King Taufa'ahau Tupou IV, then Crown Prince
-# Tungi, preferred to ensure Tonga's title as the land where time
+# Because His Majesty King Tāufaʻāhau Tupou IV, then Crown Prince
+# Tungī, preferred to ensure Tonga's title as the land where time
 # begins, the Legislative Assembly approved the latter change.
 #
 # But some of the older, more conservative members from the outer
@@ -1701,9 +1647,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # * Tonga will introduce DST in November
 #
 # I was given this link by John Letts:
-# 
 # http://news.bbc.co.uk/hi/english/world/asia-pacific/newsid_424000/424764.stm
-# 
 #
 # I have not been able to find exact dates for the transition in November
 # yet. By reading this article it seems like Fiji will be 14 hours ahead
@@ -1711,9 +1655,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # (12 + 1 hour DST).
 
 # From Arthur David Olson (1999-09-20):
-# According to 
-# http://www.tongaonline.com/news/sept1799.html
-# :
+# According to :
 # "Daylight Savings Time will take effect on Oct. 2 through April 15, 2000
 # and annually thereafter from the first Saturday in October through the
 # third Saturday of April.  Under the system approved by Privy Council on
@@ -1731,7 +1673,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # instead of the original reported date April 16. Unfortunately, the article
 # is no longer available on the site, and I did not make a copy of the
 # text, and I have forgotten to report it here.
-# (Original URL was: http://www.tongaonline.com/news/march162000.htm )
+# (Original URL was )
 
 # From Rives McDow (2000-12-01):
 # Tonga is observing DST as of 2000-11-04 and will stop on 2001-01-27.
@@ -1751,7 +1693,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # From Vernice Anderson, Personal Secretary to Philip Jessup,
 # US Ambassador At Large (oral history interview, 1971-02-02):
 #
-# Saturday, the 14th [of October, 1950] -- ...  The time was all the
+# Saturday, the 14th [of October, 1950] - ...  The time was all the
 # more confusing at that point, because we had crossed the
 # International Date Line, thus getting two Sundays.  Furthermore, we
 # discovered that Wake Island had two hours of daylight saving time
@@ -1796,7 +1738,7 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # on the high seas.  Whenever a ship was within the territorial waters of any
 # nation it would use that nation's standard time.  The captain was permitted
 # to change his ship's clocks at a time of his choice following his ship's
-# entry into another zone time--he often chose midnight.  These zones were
+# entry into another zone time - he often chose midnight.  These zones were
 # adopted by all major fleets between 1920 and 1925 but not by many
 # independent merchant ships until World War II.
 
@@ -1804,6 +1746,6 @@ Zone	Pacific/Wallis	12:15:20 -	LMT	1901
 # (2005-03-20):
 #
 # The American Practical Navigator (2002)
-# 
+# http://pollux.nss.nima.mil/pubs/pubs_j_apn_sections.html?rid=187
 # talks only about the 180-degree meridian with respect to ships in
 # international waters; it ignores the international date line.
diff --git a/jdk/make/data/tzdata/backward b/jdk/make/data/tzdata/backward
index 5afe9a317ff..ba012f45733 100644
--- a/jdk/make/data/tzdata/backward
+++ b/jdk/make/data/tzdata/backward
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # This file provides links between current names for time zones
 # and their old names.  Many names changed in late 1993.
 
+# Link	TARGET			LINK-NAME
 Link	Africa/Asmara		Africa/Asmera
-Link	Africa/Bamako		Africa/Timbuktu
+Link	Africa/Abidjan		Africa/Timbuktu
 Link	America/Argentina/Catamarca	America/Argentina/ComodRivadavia
 Link	America/Adak		America/Atka
 Link	America/Argentina/Buenos_Aires	America/Buenos_Aires
@@ -50,8 +50,11 @@ Link	America/Port_of_Spain	America/Virgin
 Link	Pacific/Auckland	Antarctica/South_Pole
 Link	Asia/Ashgabat		Asia/Ashkhabad
 Link	Asia/Kolkata		Asia/Calcutta
-Link	Asia/Chongqing		Asia/Chungking
+Link	Asia/Shanghai		Asia/Chongqing
+Link	Asia/Shanghai		Asia/Chungking
 Link	Asia/Dhaka		Asia/Dacca
+Link	Asia/Shanghai		Asia/Harbin
+Link	Asia/Urumqi		Asia/Kashgar
 Link	Asia/Kathmandu		Asia/Katmandu
 Link	Asia/Macau		Asia/Macao
 Link	Asia/Ho_Chi_Minh	Asia/Saigon
diff --git a/jdk/make/data/tzdata/etcetera b/jdk/make/data/tzdata/etcetera
index ebaa5fdfc04..d2fb91c9dd6 100644
--- a/jdk/make/data/tzdata/etcetera
+++ b/jdk/make/data/tzdata/etcetera
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
@@ -37,7 +36,7 @@ Zone	Etc/UTC		0	-	UTC
 Zone	Etc/UCT		0	-	UCT
 
 # The following link uses older naming conventions,
-# but it belongs here, not in the file `backward',
+# but it belongs here, not in the file 'backward',
 # as functions like gmtime load the "GMT" file to handle leap seconds properly.
 # We want this to work even on installations that omit the other older names.
 Link	Etc/GMT				GMT
diff --git a/jdk/make/data/tzdata/europe b/jdk/make/data/tzdata/europe
index 226c393a0f2..0c5f5667da9 100644
--- a/jdk/make/data/tzdata/europe
+++ b/jdk/make/data/tzdata/europe
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
-# From Paul Eggert (2006-03-22):
+# From Paul Eggert (2014-05-31):
 # A good source for time zone historical data outside the U.S. is
 # Thomas G. Shanks and Rique Pottenger, The International Atlas (6th edition),
 # San Diego: ACS Publications, Inc. (2003).
@@ -40,6 +40,9 @@
 # published semiannually.  Law sent in several helpful summaries
 # of the IATA's data after 1990.
 #
+# A reliable and entertaining source about time zones is
+# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#
 # Except where otherwise noted, Shanks & Pottenger is the source for
 # entries through 1991, and IATA SSIM is the source for entries afterwards.
 #
@@ -49,9 +52,9 @@
 #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
 #	which I found in the UCLA library.
 #
-#	
 #	William Willett, The Waste of Daylight, 19th edition
-#	 (1914-03)
+#	
+#	[PDF] (1914-03)
 #
 #	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
 #	.  He writes:
@@ -59,10 +62,20 @@
 #	may be sent to Mr. John Milne, Royal Geographical Society,
 #	Savile Row, London."  Nowadays please email them to tz@iana.org.
 #
-#	Brazil's Departamento Servico da Hora (DSH),
-#	
+#	Byalokoz EL. New Counting of Time in Russia since July 1, 1919.
+#	This Russian-language source was consulted by Vladimir Karpinsky; see
+#	http://mm.icann.org/pipermail/tz/2014-August/021320.html
+#	The full Russian citation is:
+#	Бялокоз, Евгений Людвигович. Новый счет времени в течении суток
+#	введенный декретом Совета народных комиссаров для всей России с 1-го
+#	июля 1919 г. / Изд. 2-е Междуведомственной комиссии. - Петроград:
+#	Десятая гос. тип., 1919.
+#	http://resolver.gpntb.ru/purl?docushare/dsweb/Get/Resource-2011/Byalokoz__E.L.__Novyy__schet__vremeni__v__techenie__sutok__izd__2(1).pdf
+#
+#	Brazil's Divisão Serviço da Hora (DSHO),
 #	History of Summer Time
-#	 (1998-09-21, in Portuguese)
+#	
+#	(1998-09-21, in Portuguese)
 
 #
 # I invented the abbreviations marked '*' in the following table;
@@ -81,10 +94,8 @@
 #        1:00       CET CEST CEMT Central Europe
 #        1:00:14    SET           Swedish (1879-1899)*
 #        2:00       EET EEST      Eastern Europe
-#        3:00       MSK MSD       Moscow
-#
-# A reliable and entertaining source about time zones, especially in Britain,
-# Derek Howse, Greenwich time and longitude, Philip Wilson Publishers (1997).
+#        3:00       FET           Further-eastern Europe*
+#        3:00       MSK MSD  MSM* Moscow
 
 # From Peter Ilieve (1994-12-04),
 # The original six [EU members]: Belgium, France, (West) Germany, Italy,
@@ -128,7 +139,7 @@
 # along the towpath within a few yards of it.'
 #
 # I have a one inch to one mile map of London and my estimate of the stone's
-# position is 51 deg. 28' 30" N, 0 deg. 18' 45" W. The longitude should
+# position is 51 degrees 28' 30" N, 0 degrees 18' 45" W. The longitude should
 # be within about +-2". The Ordnance Survey grid reference is TQ172761.
 #
 # [This yields GMTOFF = -0:01:15 for London LMT in the 18th century.]
@@ -160,8 +171,22 @@
 # transition date for London, namely 1847-12-01.  We don't know as much
 # about Dublin, so we use 1880-08-02, the legal transition time.
 
-# From Paul Eggert (2003-09-27):
-# Summer Time was first seriously proposed by William Willett (1857-1915),
+# From Paul Eggert (2014-07-19):
+# The ancients had no need for daylight saving, as they kept time
+# informally or via hours whose length depended on the time of year.
+# Daylight saving time in its modern sense was invented by the
+# New Zealand entomologist George Vernon Hudson (1867-1946),
+# whose day job as a postal clerk led him to value
+# after-hours daylight in which to pursue his research.
+# In 1895 he presented a paper to the Wellington Philosophical Society
+# that proposed a two-hour daylight-saving shift.  See:
+# Hudson GV. On seasonal time-adjustment in countries south of lat. 30 deg.
+# Transactions and Proceedings of the New Zealand Institute. 1895;28:734
+# http://rsnz.natlib.govt.nz/volume/rsnz_28/rsnz_28_00_006110.html
+# Although some interest was expressed in New Zealand, his proposal
+# did not find its way into law and eventually it was almost forgotten.
+#
+# In England, DST was independently reinvented by William Willett (1857-1915),
 # a London builder and member of the Royal Astronomical Society
 # who circulated a pamphlet "The Waste of Daylight" (1907)
 # that proposed advancing clocks 20 minutes on each of four Sundays in April,
@@ -174,7 +199,7 @@
 # A monument to Willett was unveiled on 1927-05-21, in an open space in
 # a 45-acre wood near Chislehurst, Kent that was purchased by popular
 # subscription and open to the public.  On the south face of the monolith,
-# designed by G. W. Miller, is the...William Willett Memorial Sundial,
+# designed by G. W. Miller, is the William Willett Memorial Sundial,
 # which is permanently set to Summer Time.
 
 # From Winston Churchill (1934-04-28):
@@ -183,9 +208,9 @@
 # between 160 and 170 hours more daylight leisure, to a war which
 # plunged Europe into darkness for four years, and shook the
 # foundations of civilization throughout the world.
-#	-- 
-#	"A Silent Toast to William Willett", Pictorial Weekly
-#	
+#	-- "A Silent Toast to William Willett", Pictorial Weekly;
+#	republished in Finest Hour (Spring 2002) 1(114):26
+#	http://www.winstonchurchill.org/images/finesthour/Vol.01%20No.114.pdf
 
 # From Paul Eggert (1996-09-03):
 # The OED Supplement says that the English originally said "Daylight Saving"
@@ -194,7 +219,6 @@
 # proponents (who eventually won the argument) are quoted as using "Summer".
 
 # From Arthur David Olson (1989-01-19):
-#
 # A source at the British Information Office in New York avers that it's
 # known as "British" Summer Time in all parts of the United Kingdom.
 
@@ -221,8 +245,8 @@
 # official designation; the reply of the 21st was that there wasn't
 # but he couldn't think of anything better than the "Double British
 # Summer Time" that the BBC had been using informally.
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/bbc-19410418.png
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/ho-19410421.png
+# http://www.polyomino.org.uk/british-time/bbc-19410418.png
+# http://www.polyomino.org.uk/british-time/ho-19410421.png
 
 # From Sir Alexander Maxwell in the above-mentioned letter (1941-04-21):
 # [N]o official designation has as far as I know been adopted for the time
@@ -239,23 +263,14 @@
 # the history of summer time legislation in the United Kingdom.
 # Since 1998 Joseph S. Myers has been updating
 # and extending this list, which can be found in
-# http://student.cusu.cam.ac.uk/~jsm28/british-time/
-# 
-# History of legal time in Britain
-# 
-# Rob Crowther (2012-01-04) reports that that URL no longer
-# exists, and the article can now be found at:
-# 
 # http://www.polyomino.org.uk/british-time/
-# 
 
 # From Joseph S. Myers (1998-01-06):
 #
 # The legal time in the UK outside of summer time is definitely GMT, not UTC;
 # see Lord Tanlaw's speech
-# 
-# (Lords Hansard 11 June 1997 columns 964 to 976)
-# .
+# http://www.publications.parliament.uk/pa/ld199798/ldhansrd/vo970611/text/70611-10.htm#70611-10_head0
+# (Lords Hansard 11 June 1997 columns 964 to 976).
 
 # From Paul Eggert (2006-03-22):
 #
@@ -295,8 +310,8 @@
 #   -- James Joyce, Ulysses
 
 # From Joseph S. Myers (2005-01-26):
-# Irish laws are available online at www.irishstatutebook.ie.  These include
-# various relating to legal time, for example:
+# Irish laws are available online at .
+# These include various relating to legal time, for example:
 #
 # ZZA13Y1923.html ZZA12Y1924.html ZZA8Y1925.html ZZSIV20PG1267.html
 #
@@ -458,25 +473,27 @@ Rule	GB-Eire 1990	1995	-	Oct	Sun>=22	1:00u	0	GMT
 # Use Europe/London for Jersey, Guernsey, and the Isle of Man.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1 0:00s
+Zone	Europe/London	-0:01:15 -	LMT	1847 Dec  1  0:00s
 			 0:00	GB-Eire	%s	1968 Oct 27
-			 1:00	-	BST	1971 Oct 31 2:00u
+			 1:00	-	BST	1971 Oct 31  2:00u
 			 0:00	GB-Eire	%s	1996
 			 0:00	EU	GMT/BST
 Link	Europe/London	Europe/Jersey
 Link	Europe/London	Europe/Guernsey
 Link	Europe/London	Europe/Isle_of_Man
+
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Dublin	-0:25:00 -	LMT	1880 Aug  2
-			-0:25:21 -	DMT	1916 May 21 2:00
-			-0:25:21 1:00	IST	1916 Oct  1 2:00s
+			-0:25:21 -	DMT	1916 May 21  2:00
+			-0:25:21 1:00	IST	1916 Oct  1  2:00s
 			 0:00	GB-Eire	%s	1921 Dec  6 # independence
-			 0:00	GB-Eire	GMT/IST	1940 Feb 25 2:00
-			 0:00	1:00	IST	1946 Oct  6 2:00
-			 0:00	-	GMT	1947 Mar 16 2:00
-			 0:00	1:00	IST	1947 Nov  2 2:00
-			 0:00	-	GMT	1948 Apr 18 2:00
+			 0:00	GB-Eire	GMT/IST	1940 Feb 25  2:00
+			 0:00	1:00	IST	1946 Oct  6  2:00
+			 0:00	-	GMT	1947 Mar 16  2:00
+			 0:00	1:00	IST	1947 Nov  2  2:00
+			 0:00	-	GMT	1948 Apr 18  2:00
 			 0:00	GB-Eire	GMT/IST	1968 Oct 27
-			 1:00	-	IST	1971 Oct 31 2:00u
+			 1:00	-	IST	1971 Oct 31  2:00u
 			 0:00	GB-Eire	GMT/IST	1996
 			 0:00	EU	GMT/IST
 
@@ -495,10 +512,9 @@ Rule	EU	1979	1995	-	Sep	lastSun	 1:00u	0	-
 Rule	EU	1981	max	-	Mar	lastSun	 1:00u	1:00	S
 Rule	EU	1996	max	-	Oct	lastSun	 1:00u	0	-
 # The most recent directive covers the years starting in 2002.  See:
-# 
 # Directive 2000/84/EC of the European Parliament and of the Council
 # of 19 January 2001 on summer-time arrangements.
-# 
+# http://eur-lex.europa.eu/LexUriServ/LexUriServ.do?uri=CELEX:32000L0084:EN:NOT
 
 # W-Eur differs from EU only in that W-Eur uses standard time.
 Rule	W-Eur	1977	1980	-	Apr	Sun>=1	 1:00s	1:00	S
@@ -521,18 +537,18 @@ Rule	C-Eur	1943	only	-	Oct	 4	 2:00s	0	-
 Rule	C-Eur	1944	1945	-	Apr	Mon>=1	 2:00s	1:00	S
 # Whitman gives 1944 Oct 7; go with Shanks & Pottenger.
 Rule	C-Eur	1944	only	-	Oct	 2	 2:00s	0	-
-# From Jesper Norgaard Welen (2008-07-13):
+# From Jesper Nørgaard Welen (2008-07-13):
 #
 # I found what is probably a typo of 2:00 which should perhaps be 2:00s
 # in the C-Eur rule from tz database version 2008d (this part was
-# corrected in version 2008d). The circumstancial evidence is simply the
+# corrected in version 2008d). The circumstantial evidence is simply the
 # tz database itself, as seen below:
 #
 # Zone Europe/Paris 0:09:21 - LMT 1891 Mar 15  0:01
 #    0:00 France WE%sT 1945 Sep 16  3:00
 #
 # Zone Europe/Monaco 0:29:32 - LMT 1891 Mar 15
-#    0:00 France WE%sT 1945 Sep 16 3:00
+#    0:00 France WE%sT 1945 Sep 16  3:00
 #
 # Zone Europe/Belgrade 1:22:00 - LMT 1884
 #    1:00 1:00 CEST 1945 Sep 16  2:00s
@@ -576,16 +592,16 @@ Rule	E-Eur	1981	max	-	Mar	lastSun	 0:00	1:00	S
 Rule	E-Eur	1996	max	-	Oct	lastSun	 0:00	0	-
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST	# Moscow Summer Time
-Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT	# Moscow Mean Time
-Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST	# Moscow Double Summer Time
+Rule	Russia	1917	only	-	Jul	 1	23:00	1:00	MST  # Moscow Summer Time
+Rule	Russia	1917	only	-	Dec	28	 0:00	0	MMT  # Moscow Mean Time
+Rule	Russia	1918	only	-	May	31	22:00	2:00	MDST # Moscow Double Summer Time
 Rule	Russia	1918	only	-	Sep	16	 1:00	1:00	MST
 Rule	Russia	1919	only	-	May	31	23:00	2:00	MDST
-Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	S
-Rule	Russia	1919	only	-	Aug	16	 0:00	0	-
-Rule	Russia	1921	only	-	Feb	14	23:00	1:00	S
-Rule	Russia	1921	only	-	Mar	20	23:00	2:00	M # Midsummer
-Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	S
+Rule	Russia	1919	only	-	Jul	 1	 2:00	1:00	MSD
+Rule	Russia	1919	only	-	Aug	16	 0:00	0	MSK
+Rule	Russia	1921	only	-	Feb	14	23:00	1:00	MSD
+Rule	Russia	1921	only	-	Mar	20	23:00	2:00	MSM  # Midsummer
+Rule	Russia	1921	only	-	Sep	 1	 0:00	1:00	MSD
 Rule	Russia	1921	only	-	Oct	 1	 0:00	0	-
 # Act No.925 of the Council of Ministers of the USSR (1980-10-24):
 Rule	Russia	1981	1984	-	Apr	 1	 0:00	1:00	S
@@ -607,14 +623,10 @@ Rule	Russia	1996	2010	-	Oct	lastSun	 2:00s	0	-
 # According to the law Russia is abolishing daylight saving time.
 #
 # Medvedev signed a law "On the Calculation of Time" (in russian):
-# 
 # http://bmockbe.ru/events/?ID=7583
-# 
 #
 # Medvedev signed a law on the calculation of the time (in russian):
-# 
 # http://www.regnum.ru/news/polit/1413906.html
-# 
 
 # From Arthur David Olson (2011-06-15):
 # Take "abolishing daylight saving time" to mean that time is now considered
@@ -634,10 +646,10 @@ Zone	EET		2:00	EU	EE%sT
 # From Markus Kuhn (1996-07-12):
 # The official German names ... are
 #
-#	Mitteleuropaeische Zeit (MEZ)         = UTC+01:00
-#	Mitteleuropaeische Sommerzeit (MESZ)  = UTC+02:00
+#	Mitteleuropäische Zeit (MEZ)         = UTC+01:00
+#	Mitteleuropäische Sommerzeit (MESZ)  = UTC+02:00
 #
-# as defined in the German Time Act (Gesetz ueber die Zeitbestimmung (ZeitG),
+# as defined in the German Time Act (Gesetz über die Zeitbestimmung (ZeitG),
 # 1978-07-25, Bundesgesetzblatt, Jahrgang 1978, Teil I, S. 1110-1111)....
 # I wrote ... to the German Federal Physical-Technical Institution
 #
@@ -692,7 +704,7 @@ Zone	Europe/Tirane	1:19:20 -	LMT	1914
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Andorra	0:06:04 -	LMT	1901
 			0:00	-	WET	1946 Sep 30
-			1:00	-	CET	1985 Mar 31 2:00
+			1:00	-	CET	1985 Mar 31  2:00
 			1:00	EU	CE%sT
 
 # Austria
@@ -718,9 +730,9 @@ Rule	Austria	1980	only	-	Sep	28	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Vienna	1:05:21 -	LMT	1893 Apr
 			1:00	C-Eur	CE%sT	1920
-			1:00	Austria	CE%sT	1940 Apr  1 2:00s
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
-			1:00	1:00	CEST	1945 Apr 12 2:00s
+			1:00	Austria	CE%sT	1940 Apr  1  2:00s
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
+			1:00	1:00	CEST	1945 Apr 12  2:00s
 			1:00	-	CET	1946
 			1:00	Austria	CE%sT	1981
 			1:00	EU	CE%sT
@@ -731,38 +743,29 @@ Zone	Europe/Vienna	1:05:21 -	LMT	1893 Apr
 # GMT+3 without DST (was GMT+2 with DST).
 #
 # Sources (Russian language):
-# 1.
-# 
 # http://www.belta.by/ru/all_news/society/V-Belarusi-otmenjaetsja-perexod-na-sezonnoe-vremja_i_572952.html
-# 
-# 2.
-# 
 # http://naviny.by/rubrics/society/2011/09/16/ic_articles_116_175144/
-# 
-# 3.
-# 
 # http://news.tut.by/society/250578.html
-# 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Minsk	1:50:16 -	LMT	1880
-			1:50	-	MMT	1924 May 2 # Minsk Mean Time
+			1:50	-	MMT	1924 May  2 # Minsk Mean Time
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Jun 28
 			1:00	C-Eur	CE%sT	1944 Jul  3
 			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1991 Mar 31 2:00s
-			2:00	1:00	EEST	1991 Sep 29 2:00s
-			2:00	-	EET	1992 Mar 29 0:00s
-			2:00	1:00	EEST	1992 Sep 27 0:00s
-			2:00	Russia	EE%sT	2011 Mar 27 2:00s
-			3:00	-	FET # Further-eastern European Time
+			3:00	-	MSK	1991 Mar 31  2:00s
+			2:00	1:00	EEST	1991 Sep 29  2:00s
+			2:00	-	EET	1992 Mar 29  0:00s
+			2:00	1:00	EEST	1992 Sep 27  0:00s
+			2:00	Russia	EE%sT	2011 Mar 27  2:00s
+			3:00	-	FET
 
 # Belgium
 #
 # From Paul Eggert (1997-07-02):
 # Entries from 1918 through 1991 are taken from:
 #	Annuaire de L'Observatoire Royal de Belgique,
-#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe annee, 1991
+#	Avenue Circulaire, 3, B-1180 BRUXELLES, CLVIIe année, 1991
 #	(Imprimerie HAYEZ, s.p.r.l., Rue Fin, 4, 1080 BRUXELLES, MCMXC),
 #	pp 8-9.
 # LMT before 1892 was 0:17:30, according to the official journal of Belgium:
@@ -812,7 +815,7 @@ Rule	Belgium	1946	only	-	May	19	 2:00s	1:00	S
 Rule	Belgium	1946	only	-	Oct	 7	 2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Brussels	0:17:30 -	LMT	1880
-			0:17:30	-	BMT	1892 May  1 12:00 # Brussels MT
+			0:17:30	-	BMT	1892 May  1 12:00  # Brussels MT
 			0:00	-	WET	1914 Nov  8
 			1:00	-	CET	1916 May  1  0:00
 			1:00	C-Eur	CE%sT	1918 Nov 11 11:00u
@@ -828,8 +831,8 @@ Zone	Europe/Brussels	0:17:30 -	LMT	1880
 #
 # From Plamen Simenov via Steffen Thorsen (1999-09-09):
 # A document of Government of Bulgaria (No.94/1997) says:
-# EET --> EETDST is in 03:00 Local time in last Sunday of March ...
-# EETDST --> EET is in 04:00 Local time in last Sunday of October
+# EET -> EETDST is in 03:00 Local time in last Sunday of March ...
+# EETDST -> EET is in 04:00 Local time in last Sunday of October
 #
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Bulg	1979	only	-	Mar	31	23:00	1:00	S
@@ -842,7 +845,7 @@ Zone	Europe/Sofia	1:33:16 -	LMT	1880
 			1:56:56	-	IMT	1894 Nov 30 # Istanbul MT?
 			2:00	-	EET	1942 Nov  2  3:00
 			1:00	C-Eur	CE%sT	1945
-			1:00	-	CET	1945 Apr 2 3:00
+			1:00	-	CET	1945 Apr  2  3:00
 			2:00	-	EET	1979 Mar 31 23:00
 			2:00	Bulg	EE%sT	1982 Sep 26  2:00
 			2:00	C-Eur	EE%sT	1991
@@ -866,15 +869,15 @@ Rule	Czech	1948	only	-	Apr	18	2:00s	1:00	S
 Rule	Czech	1949	only	-	Apr	 9	2:00s	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Prague	0:57:44 -	LMT	1850
-			0:57:44	-	PMT	1891 Oct     # Prague Mean Time
-			1:00	C-Eur	CE%sT	1944 Sep 17 2:00s
+			0:57:44	-	PMT	1891 Oct    # Prague Mean Time
+			1:00	C-Eur	CE%sT	1944 Sep 17  2:00s
 			1:00	Czech	CE%sT	1979
 			1:00	EU	CE%sT
 # Use Europe/Prague also for Slovakia.
 
 # Denmark, Faroe Islands, and Greenland
 
-# From Jesper Norgaard Welen (2005-04-26):
+# From Jesper Nørgaard Welen (2005-04-26):
 # http://www.hum.aau.dk/~poe/tid/tine/DanskTid.htm says that the law
 # [introducing standard time] was in effect from 1894-01-01....
 # The page http://www.retsinfo.dk/_GETDOCI_/ACCN/A18930008330-REGL
@@ -884,7 +887,7 @@ Zone	Europe/Prague	0:57:44 -	LMT	1850
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/A19722110030-REGL
 #
 # This provoked a new law from 1974 to make possible summer time changes
-# in subsequenet decrees with the law
+# in subsequent decrees with the law
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/A19740022330-REGL
 #
 # It seems however that no decree was set forward until 1980.  I have
@@ -899,7 +902,7 @@ Zone	Europe/Prague	0:57:44 -	LMT	1850
 # was suspended on that night):
 # http://www.retsinfo.dk/_GETDOCI_/ACCN/C19801120554-REGL
 
-# From Jesper Norgaard Welen (2005-06-11):
+# From Jesper Nørgaard Welen (2005-06-11):
 # The Herning Folkeblad (1980-09-26) reported that the night between
 # Saturday and Sunday the clock is set back from three to two.
 
@@ -923,11 +926,11 @@ Rule	Denmark	1948	only	-	Aug	 8	 2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Copenhagen	 0:50:20 -	LMT	1890
 			 0:50:20 -	CMT	1894 Jan  1 # Copenhagen MT
-			 1:00	Denmark	CE%sT	1942 Nov  2 2:00s
-			 1:00	C-Eur	CE%sT	1945 Apr  2 2:00
+			 1:00	Denmark	CE%sT	1942 Nov  2  2:00s
+			 1:00	C-Eur	CE%sT	1945 Apr  2  2:00
 			 1:00	Denmark	CE%sT	1980
 			 1:00	EU	CE%sT
-Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
+Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11 # Tórshavn
 			 0:00	-	WET	1981
 			 0:00	EU	WE%sT
 #
@@ -939,11 +942,11 @@ Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
 # From Paul Eggert (2006-03-22):
 # Greenland joined the EU as part of Denmark, obtained home rule on 1979-05-01,
 # and left the EU on 1985-02-01.  It therefore should have been using EU
-# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthab
+# rules at least through 1984.  Shanks & Pottenger say Scoresbysund and Godthåb
 # used C-Eur rules after 1980, but IATA SSIM (1991/1996) says they use EU
 # rules since at least 1991.  Assume EU rules since 1980.
 
-# From Gwillin Law (2001-06-06), citing
+# From Gwillim Law (2001-06-06), citing
 #  (2001-03-15),
 # and with translations corrected by Steffen Thorsen:
 #
@@ -978,16 +981,16 @@ Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
 # DPC research station at Zackenberg.
 #
 # Scoresbysund and two small villages nearby keep time UTC-1 and use
-# the same daylight savings time period as in West Greenland (Godthab).
+# the same daylight savings time period as in West Greenland (Godthåb).
 #
-# The rest of Greenland, including Godthab (this area, although it
+# The rest of Greenland, including Godthåb (this area, although it
 # includes central Greenland, is known as west Greenland), keeps time
 # UTC-3, with daylight savings methods according to European rules.
 #
 # It is common procedure to use UTC 0 in the wilderness of East and
 # North Greenland, because it is mainly Icelandic aircraft operators
 # maintaining traffic in these areas.  However, the official status of
-# this area is that it sticks with Godthab time.  This area might be
+# this area is that it sticks with Godthåb time.  This area might be
 # considered a dual time zone in some respects because of this.
 
 # From Rives McDow (2001-11-19):
@@ -996,8 +999,8 @@ Zone Atlantic/Faroe	-0:27:04 -	LMT	1908 Jan 11	# Torshavn
 
 # From Paul Eggert (2006-03-22):
 # From 1997 on the CIA map shows Danmarkshavn on GMT;
-# the 1995 map as like Godthab.
-# For lack of better info, assume they were like Godthab before 1996.
+# the 1995 map as like Godthåb.
+# For lack of better info, assume they were like Godthåb before 1996.
 # startkart.no says Thule does not observe DST, but this is clearly an error,
 # so go with Shanks & Pottenger for Thule transitions until this year.
 # For 2007 on assume Thule will stay in sync with US DST rules.
@@ -1012,15 +1015,15 @@ Rule	Thule	2007	max	-	Nov	Sun>=1	2:00	0	S
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Danmarkshavn -1:14:40 -	LMT	1916 Jul 28
-			-3:00	-	WGT	1980 Apr  6 2:00
+			-3:00	-	WGT	1980 Apr  6  2:00
 			-3:00	EU	WG%sT	1996
 			0:00	-	GMT
 Zone America/Scoresbysund -1:27:52 -	LMT	1916 Jul 28 # Ittoqqortoormiit
-			-2:00	-	CGT	1980 Apr  6 2:00
+			-2:00	-	CGT	1980 Apr  6  2:00
 			-2:00	C-Eur	CG%sT	1981 Mar 29
 			-1:00	EU	EG%sT
 Zone America/Godthab	-3:26:56 -	LMT	1916 Jul 28 # Nuuk
-			-3:00	-	WGT	1980 Apr  6 2:00
+			-3:00	-	WGT	1980 Apr  6  2:00
 			-3:00	EU	WG%sT
 Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
 			-4:00	Thule	A%sT
@@ -1042,17 +1045,16 @@ Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
 # summer time next spring."
 
 # From Peter Ilieve (1998-11-04), heavily edited:
-# 
 # The 1998-09-22 Estonian time law
-# 
+# http://trip.rk.ee/cgi-bin/thw?${BASE}=akt&${OOHTML}=rtd&TA=1998&TO=1&AN=1390
 # refers to the Eighth Directive and cites the association agreement between
-# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22--27, 120).
+# the EU and Estonia, ratified by the Estonian law (RT II 1995, 22-27, 120).
 #
 # I also asked [my relative] whether they use any standard abbreviation
 # for their standard and summer times. He says no, they use "suveaeg"
 # (summer time) and "talveaeg" (winter time).
 
-# From The Baltic Times (1999-09-09)
+# From The Baltic Times  (1999-09-09)
 # via Steffen Thorsen:
 # This year will mark the last time Estonia shifts to summer time,
 # a council of the ruling coalition announced Sept. 6....
@@ -1070,19 +1072,19 @@ Zone America/Thule	-4:35:08 -	LMT	1916 Jul 28 # Pituffik air base
 # The Estonian government has changed once again timezone politics.
 # Now we are using again EU rules.
 #
-# From Urmet Jaanes (2002-03-28):
+# From Urmet Jänes (2002-03-28):
 # The legislative reference is Government decree No. 84 on 2002-02-21.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Tallinn	1:39:00	-	LMT	1880
-			1:39:00	-	TMT	1918 Feb # Tallinn Mean Time
+			1:39:00	-	TMT	1918 Feb    # Tallinn Mean Time
 			1:00	C-Eur	CE%sT	1919 Jul
 			1:39:00	-	TMT	1921 May
 			2:00	-	EET	1940 Aug  6
 			3:00	-	MSK	1941 Sep 15
 			1:00	C-Eur	CE%sT	1944 Sep 22
-			3:00	Russia	MSK/MSD	1989 Mar 26 2:00s
-			2:00	1:00	EEST	1989 Sep 24 2:00s
+			3:00	Russia	MSK/MSD	1989 Mar 26  2:00s
+			2:00	1:00	EEST	1989 Sep 24  2:00s
 			2:00	C-Eur	EE%sT	1998 Sep 22
 			2:00	EU	EE%sT	1999 Nov  1
 			2:00	-	EET	2002 Feb 21
@@ -1104,35 +1106,45 @@ Zone	Europe/Tallinn	1:39:00	-	LMT	1880
 # This is documented in Heikki Oja: Aikakirja 2007, published by The Almanac
 # Office of University of Helsinki, ISBN 952-10-3221-9, available online (in
 # Finnish) at
-#
-# 
 # http://almanakka.helsinki.fi/aikakirja/Aikakirja2007kokonaan.pdf
-# 
 #
 # Page 105 (56 in PDF version) has a handy table of all past daylight savings
 # transitions. It is easy enough to interpret without Finnish skills.
 #
 # This is also confirmed by Finnish Broadcasting Company's archive at:
-#
-# 
 # http://www.yle.fi/elavaarkisto/?s=s&g=1&ag=5&t=&a=3401
-# 
 #
 # The news clip from 1981 says that "the time between 2 and 3 o'clock does not
 # exist tonight."
 
+# From Konstantin Hyppönen (2014-06-13):
+# [Heikki Oja's book Aikakirja 2013]
+# http://almanakka.helsinki.fi/images/aikakirja/Aikakirja2013kokonaan.pdf
+# pages 104-105, including a scan from a newspaper published on Apr 2 1942
+# say that ... [o]n Apr 2 1942, 24 o'clock (which means Apr 3 1942,
+# 00:00), clocks were moved one hour forward. The newspaper
+# mentions "on the night from Thursday to Friday"....
+# On Oct 4 1942, clocks were moved at 1:00 one hour backwards.
+#
+# From Paul Eggert (2014-06-14):
+# Go with Oja over Shanks.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	Finland	1942	only	-	Apr	3	0:00	1:00	S
-Rule	Finland	1942	only	-	Oct	3	0:00	0	-
+Rule	Finland	1942	only	-	Apr	2	24:00	1:00	S
+Rule	Finland	1942	only	-	Oct	4	1:00	0	-
 Rule	Finland	1981	1982	-	Mar	lastSun	2:00	1:00	S
 Rule	Finland	1981	1982	-	Sep	lastSun	3:00	0	-
+
+# Milne says Helsinki (Helsingfors) time was 1:39:49.2 (official document);
+# round to nearest.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Helsinki	1:39:52 -	LMT	1878 May 31
-			1:39:52	-	HMT	1921 May    # Helsinki Mean Time
+Zone	Europe/Helsinki	1:39:49 -	LMT	1878 May 31
+			1:39:49	-	HMT	1921 May    # Helsinki Mean Time
 			2:00	Finland	EE%sT	1983
 			2:00	EU	EE%sT
 
-# Aaland Is
+# Åland Is
 Link	Europe/Helsinki	Europe/Mariehamn
 
 
@@ -1140,14 +1152,14 @@ Link	Europe/Helsinki	Europe/Mariehamn
 
 # From Ciro Discepolo (2000-12-20):
 #
-# Henri Le Corre, Regimes Horaires pour le monde entier, Editions
+# Henri Le Corre, Régimes horaires pour le monde entier, Éditions
 # Traditionnelles - Paris 2 books, 1993
 #
-# Gabriel, Traite de l'heure dans le monde, Guy Tredaniel editeur,
+# Gabriel, Traité de l'heure dans le monde, Guy Trédaniel,
 # Paris, 1991
 #
-# Francoise Gauquelin, Problemes de l'heure resolus en astrologie,
-# Guy tredaniel, Paris 1987
+# Françoise Gauquelin, Problèmes de l'heure résolus en astrologie,
+# Guy Trédaniel, Paris 1987
 
 
 #
@@ -1188,16 +1200,16 @@ Rule	France	1939	only	-	Nov	18	23:00s	0	-
 Rule	France	1940	only	-	Feb	25	 2:00	1:00	S
 # The French rules for 1941-1944 were not used in Paris, but Shanks & Pottenger
 # write that they were used in Monaco and in many French locations.
-# Le Corre writes that the upper limit of the free zone was Arneguy, Orthez,
-# Mont-de-Marsan, Bazas, Langon, Lamotte-Montravel, Marouil, La
-# Rochefoucault, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
+# Le Corre writes that the upper limit of the free zone was Arnéguy, Orthez,
+# Mont-de-Marsan, Bazas, Langon, Lamothe-Montravel, Marœuil, La
+# Rochefoucauld, Champagne-Mouton, La Roche-Posay, La Haye-Descartes,
 # Loches, Montrichard, Vierzon, Bourges, Moulins, Digoin,
-# Paray-le-Monial, Montceau-les-Mines, Chalons-sur-Saone, Arbois,
+# Paray-le-Monial, Montceau-les-Mines, Chalon-sur-Saône, Arbois,
 # Dole, Morez, St-Claude, and Collonges (Haute-Savoie).
 Rule	France	1941	only	-	May	 5	 0:00	2:00	M # Midsummer
 # Shanks & Pottenger say this transition occurred at Oct 6 1:00,
 # but go with Denis Excoffier (1997-12-12),
-# who quotes the Ephemerides Astronomiques for 1998 from Bureau des Longitudes
+# who quotes the Ephémérides astronomiques for 1998 from Bureau des Longitudes
 # as saying 5/10/41 22hUT.
 Rule	France	1941	only	-	Oct	 6	 0:00	1:00	S
 Rule	France	1942	only	-	Mar	 9	 0:00	2:00	M
@@ -1218,7 +1230,7 @@ Rule	France	1976	only	-	Sep	26	 1:00	0	-
 # on PMT-0:09:21 until 1978-08-09, when the time base finally switched to UTC.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Paris	0:09:21 -	LMT	1891 Mar 15  0:01
-			0:09:21	-	PMT	1911 Mar 11  0:01  # Paris MT
+			0:09:21	-	PMT	1911 Mar 11  0:01 # Paris MT
 # Shanks & Pottenger give 1940 Jun 14 0:00; go with Excoffier and Le Corre.
 			0:00	France	WE%sT	1940 Jun 14 23:00
 # Le Corre says Paris stuck with occupied-France time after the liberation;
@@ -1235,15 +1247,13 @@ Zone	Europe/Paris	0:09:21 -	LMT	1891 Mar 15  0:01
 # Bundesanstalt contains DST information back to 1916.
 # [See tz-link.htm for the URL.]
 
-# From Joerg Schilling (2002-10-23):
+# From Jörg Schilling (2002-10-23):
 # In 1945, Berlin was switched to Moscow Summer time (GMT+4) by
-# 
-# General [Nikolai] Bersarin.
+# http://www.dhm.de/lemo/html/biografien/BersarinNikolai/
+# General [Nikolai] Bersarin.
 
 # From Paul Eggert (2003-03-08):
-# 
 # http://www.parlament-berlin.de/pds-fraktion.nsf/727459127c8b66ee8525662300459099/defc77cb784f180ac1256c2b0030274b/$FILE/bersarint.pdf
-# 
 # says that Bersarin issued an order to use Moscow time on May 20.
 # However, Moscow did not observe daylight saving in 1945, so
 # this was equivalent to CEMT (GMT+3), not GMT+4.
@@ -1268,23 +1278,23 @@ Rule SovietZone	1945	only	-	Nov	18	2:00s	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Berlin	0:53:28 -	LMT	1893 Apr
-			1:00	C-Eur	CE%sT	1945 May 24 2:00
+			1:00	C-Eur	CE%sT	1945 May 24  2:00
 			1:00 SovietZone	CE%sT	1946
 			1:00	Germany	CE%sT	1980
 			1:00	EU	CE%sT
 
 # From Tobias Conradi (2011-09-12):
-# Busingen , surrounded by the Swiss canton
+# Büsingen , surrounded by the Swiss canton
 # Schaffhausen, did not start observing DST in 1980 as the rest of DE
 # (West Germany at that time) and DD (East Germany at that time) did.
 # DD merged into DE, the area is currently covered by code DE in ISO 3166-1,
 # which in turn is covered by the zone Europe/Berlin.
 #
-# Source for the time in Busingen 1980:
+# Source for the time in Büsingen 1980:
 # http://www.srf.ch/player/video?id=c012c029-03b7-4c2b-9164-aa5902cd58d3
 
 # From Arthur David Olson (2012-03-03):
-# Busingen and Zurich have shared clocks since 1970.
+# Büsingen and Zurich have shared clocks since 1970.
 
 Link	Europe/Zurich	Europe/Busingen
 
@@ -1295,8 +1305,8 @@ Link	Europe/Zurich	Europe/Busingen
 
 # Gibraltar
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2 0:00s
-			0:00	GB-Eire	%s	1957 Apr 14 2:00
+Zone Europe/Gibraltar	-0:21:24 -	LMT	1880 Aug  2  0:00s
+			0:00	GB-Eire	%s	1957 Apr 14  2:00
 			1:00	-	CET	1982
 			1:00	EU	CE%sT
 
@@ -1327,7 +1337,7 @@ Rule	Greece	1980	only	-	Apr	 1	0:00	1:00	S
 Rule	Greece	1980	only	-	Sep	28	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Athens	1:34:52 -	LMT	1895 Sep 14
-			1:34:52	-	AMT	1916 Jul 28 0:01     # Athens MT
+			1:34:52	-	AMT	1916 Jul 28  0:01 # Athens MT
 			2:00	Greece	EE%sT	1941 Apr 30
 			1:00	Greece	CE%sT	1944 Apr  4
 			2:00	Greece	EE%sT	1981
@@ -1336,15 +1346,20 @@ Zone	Europe/Athens	1:34:52 -	LMT	1895 Sep 14
 			2:00	EU	EE%sT
 
 # Hungary
+# From Paul Eggert (2014-07-15):
+# Dates for 1916-1945 are taken from:
+# Oross A. Jelen a múlt jövője: a nyári időszámítás Magyarországon 1916-1945.
+# National Archives of Hungary (2012-10-29).
+# http://mnl.gov.hu/a_het_dokumentuma/a_nyari_idoszamitas_magyarorszagon_19161945.html
+# This source does not always give times, which are taken from Shanks
+# & Pottenger (which disagree about the dates).
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Hungary	1918	only	-	Apr	 1	 3:00	1:00	S
-Rule	Hungary	1918	only	-	Sep	29	 3:00	0	-
+Rule	Hungary	1918	only	-	Sep	16	 3:00	0	-
 Rule	Hungary	1919	only	-	Apr	15	 3:00	1:00	S
-Rule	Hungary	1919	only	-	Sep	15	 3:00	0	-
-Rule	Hungary	1920	only	-	Apr	 5	 3:00	1:00	S
-Rule	Hungary	1920	only	-	Sep	30	 3:00	0	-
+Rule	Hungary	1919	only	-	Nov	24	 3:00	0	-
 Rule	Hungary	1945	only	-	May	 1	23:00	1:00	S
-Rule	Hungary	1945	only	-	Nov	 3	 0:00	0	-
+Rule	Hungary	1945	only	-	Nov	 1	 0:00	0	-
 Rule	Hungary	1946	only	-	Mar	31	 2:00s	1:00	S
 Rule	Hungary	1946	1949	-	Oct	Sun>=1	 2:00s	0	-
 Rule	Hungary	1947	1949	-	Apr	Sun>=4	 2:00s	1:00	S
@@ -1360,7 +1375,7 @@ Rule	Hungary	1980	only	-	Apr	 6	 1:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Budapest	1:16:20 -	LMT	1890 Oct
 			1:00	C-Eur	CE%sT	1918
-			1:00	Hungary	CE%sT	1941 Apr  6  2:00
+			1:00	Hungary	CE%sT	1941 Apr  8
 			1:00	C-Eur	CE%sT	1945
 			1:00	Hungary	CE%sT	1980 Sep 28  2:00s
 			1:00	EU	CE%sT
@@ -1423,7 +1438,7 @@ Rule	Iceland	1967	only	-	Oct	29	 1:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Reykjavik	-1:27:24 -	LMT	1837
 			-1:27:48 -	RMT	1908 # Reykjavik Mean Time?
-			-1:00	Iceland	IS%sT	1968 Apr 7 1:00s
+			-1:00	Iceland	IS%sT	1968 Apr  7  1:00s
 			 0:00	-	GMT
 
 # Italy
@@ -1438,9 +1453,8 @@ Zone Atlantic/Reykjavik	-1:27:24 -	LMT	1837
 # From Paul Eggert (2006-03-22):
 # For Italian DST we have three sources: Shanks & Pottenger, Whitman, and
 # F. Pollastri
-# 
 # Day-light Saving Time in Italy (2006-02-03)
-# 
+# http://toi.iriti.cnr.it/uk/ienitlt.html
 # ('FP' below), taken from an Italian National Electrotechnical Institute
 # publication. When the three sources disagree, guess who's right, as follows:
 #
@@ -1500,8 +1514,8 @@ Rule	Italy	1978	only	-	Oct	 1	0:00s	0	-
 Rule	Italy	1979	only	-	Sep	30	0:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Rome	0:49:56 -	LMT	1866 Sep 22
-			0:49:56	-	RMT	1893 Nov  1 0:00s # Rome Mean
-			1:00	Italy	CE%sT	1942 Nov  2 2:00s
+			0:49:56	-	RMT	1893 Nov  1  0:00s # Rome Mean
+			1:00	Italy	CE%sT	1942 Nov  2  2:00s
 			1:00	C-Eur	CE%sT	1944 Jul
 			1:00	Italy	CE%sT	1980
 			1:00	EU	CE%sT
@@ -1548,18 +1562,18 @@ Link	Europe/Rome	Europe/San_Marino
 
 # From Andrei Ivanov (2000-03-06):
 # This year Latvia will not switch to Daylight Savings Time (as specified in
-# 
 # The Regulations of the Cabinet of Ministers of the Rep. of Latvia of
-# 29-Feb-2000 (#79), in Latvian for subscribers only).
+# 29-Feb-2000 (#79) ,
+# in Latvian for subscribers only).
 
-# 
-# From RFE/RL Newsline (2001-01-03), noted after a heads-up by Rives McDow:
-# 
+# From RFE/RL Newsline
+# http://www.rferl.org/newsline/2001/01/3-CEE/cee-030101.html
+# (2001-01-03), noted after a heads-up by Rives McDow:
 # The Latvian government on 2 January decided that the country will
 # institute daylight-saving time this spring, LETA reported.
 # Last February the three Baltic states decided not to turn back their
 # clocks one hour in the spring....
-# Minister of Economy Aigars Kalvitis noted that Latvia had too few
+# Minister of Economy Aigars Kalvītis noted that Latvia had too few
 # daylight hours and thus decided to comply with a draft European
 # Commission directive that provides for instituting daylight-saving
 # time in EU countries between 2002 and 2006. The Latvian government
@@ -1569,18 +1583,23 @@ Link	Europe/Rome	Europe/San_Marino
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Latvia	1989	1996	-	Mar	lastSun	 2:00s	1:00	S
 Rule	Latvia	1989	1996	-	Sep	lastSun	 2:00s	0	-
+
+# Milne 1899 says Riga was 1:36:28 (Polytechnique House time).
+# Byalokoz 1919 says Latvia was 1:36:34.
+# Go with Byalokoz.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Riga	1:36:24	-	LMT	1880
-			1:36:24	-	RMT	1918 Apr 15 2:00 #Riga Mean Time
-			1:36:24	1:00	LST	1918 Sep 16 3:00 #Latvian Summer
-			1:36:24	-	RMT	1919 Apr  1 2:00
-			1:36:24	1:00	LST	1919 May 22 3:00
-			1:36:24	-	RMT	1926 May 11
+Zone	Europe/Riga	1:36:34	-	LMT	1880
+			1:36:34	-	RMT	1918 Apr 15  2:00 # Riga MT
+			1:36:34	1:00	LST	1918 Sep 16  3:00 # Latvian ST
+			1:36:34	-	RMT	1919 Apr  1  2:00
+			1:36:34	1:00	LST	1919 May 22  3:00
+			1:36:34	-	RMT	1926 May 11
 			2:00	-	EET	1940 Aug  5
 			3:00	-	MSK	1941 Jul
 			1:00	C-Eur	CE%sT	1944 Oct 13
-			3:00	Russia	MSK/MSD	1989 Mar lastSun 2:00s
-			2:00	1:00	EEST	1989 Sep lastSun 2:00s
+			3:00	Russia	MSK/MSD	1989 Mar lastSun  2:00s
+			2:00	1:00	EEST	1989 Sep lastSun  2:00s
 			2:00	Latvia	EE%sT	1997 Jan 21
 			2:00	EU	EE%sT	2000 Feb 29
 			2:00	-	EET	2001 Jan  2
@@ -1614,7 +1633,7 @@ Link Europe/Zurich Europe/Vaduz
 # I would like to inform that in this year Lithuanian time zone
 # (Europe/Vilnius) was changed.
 
-# From ELTA No. 972 (2582) (1999-09-29),
+# From ELTA No. 972 (2582) (1999-09-29) ,
 # via Steffen Thorsen:
 # Lithuania has shifted back to the second time zone (GMT plus two hours)
 # to be valid here starting from October 31,
@@ -1623,9 +1642,9 @@ Link Europe/Zurich Europe/Vaduz
 # motion to give up shifting to summer time in spring, as it was
 # already done by Estonia.
 
-# From the 
-# Fact File, Lithuanian State Department of Tourism
-#  (2000-03-27): Local time is GMT+2 hours ..., no daylight saving.
+# From the Fact File, Lithuanian State Department of Tourism
+#  (2000-03-27):
+# Local time is GMT+2 hours ..., no daylight saving.
 
 # From a user via Klaus Marten (2003-02-07):
 # As a candidate for membership of the European Union, Lithuania will
@@ -1638,18 +1657,18 @@ Link Europe/Zurich Europe/Vaduz
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Vilnius	1:41:16	-	LMT	1880
-			1:24:00	-	WMT	1917	    # Warsaw Mean Time
+			1:24:00	-	WMT	1917        # Warsaw Mean Time
 			1:35:36	-	KMT	1919 Oct 10 # Kaunas Mean Time
 			1:00	-	CET	1920 Jul 12
 			2:00	-	EET	1920 Oct  9
 			1:00	-	CET	1940 Aug  3
 			3:00	-	MSK	1941 Jun 24
 			1:00	C-Eur	CE%sT	1944 Aug
-			3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			2:00	1:00	EEST	1991 Sep 29 2:00s
+			3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			2:00	1:00	EEST	1991 Sep 29  2:00s
 			2:00	C-Eur	EE%sT	1998
-			2:00	-	EET	1998 Mar 29 1:00u
-			1:00	EU	CE%sT	1999 Oct 31 1:00u
+			2:00	-	EET	1998 Mar 29  1:00u
+			1:00	EU	CE%sT	1999 Oct 31  1:00u
 			2:00	-	EET	2003 Jan  1
 			2:00	EU	EE%sT
 
@@ -1683,9 +1702,9 @@ Rule	Lux	1929	only	-	Apr	20	23:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Luxembourg	0:24:36 -	LMT	1904 Jun
 			1:00	Lux	CE%sT	1918 Nov 25
-			0:00	Lux	WE%sT	1929 Oct  6 2:00s
-			0:00	Belgium	WE%sT	1940 May 14 3:00
-			1:00	C-Eur	WE%sT	1944 Sep 18 3:00
+			0:00	Lux	WE%sT	1929 Oct  6  2:00s
+			0:00	Belgium	WE%sT	1940 May 14  3:00
+			1:00	C-Eur	WE%sT	1944 Sep 18  3:00
 			1:00	Belgium	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1702,9 +1721,9 @@ Rule	Malta	1975	1979	-	Apr	Sun>=15	2:00	1:00	S
 Rule	Malta	1975	1980	-	Sep	Sun>=15	2:00	0	-
 Rule	Malta	1980	only	-	Mar	31	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
-			1:00	Italy	CE%sT	1942 Nov  2 2:00s
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00s
+Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2  0:00s # Valletta
+			1:00	Italy	CE%sT	1942 Nov  2  2:00s
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00s
 			1:00	Italy	CE%sT	1973 Mar 31
 			1:00	Malta	CE%sT	1981
 			1:00	EU	CE%sT
@@ -1719,7 +1738,7 @@ Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
 # In early 1992 there was large-scale interethnic violence in the area
 # and it's possible that some Russophones continued to observe Moscow time.
 # But [two people] separately reported via
-# Jesper Norgaard that as of 2001-01-24 Tiraspol was like Chisinau.
+# Jesper Nørgaard that as of 2001-01-24 Tiraspol was like Chisinau.
 # The Tiraspol entry has therefore been removed for now.
 #
 # From Alexander Krivenyshev (2011-10-17):
@@ -1728,13 +1747,8 @@ Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
 # to the Winter Time).
 #
 # News (in Russian):
-# 
 # http://www.kyivpost.ua/russia/news/pridnestrove-otkazalos-ot-perehoda-na-zimnee-vremya-30954.html
-# 
-#
-# 
 # http://www.allmoldova.com/moldova-news/1249064116.html
-# 
 #
 # The substance of this change (reinstatement of the Tiraspol entry)
 # is from a patch from Petr Machata (2011-10-17)
@@ -1752,9 +1766,7 @@ Zone	Europe/Malta	0:58:04 -	LMT	1893 Nov  2 0:00s # Valletta
 # Following Moldova and neighboring Ukraine- Transnistria (Pridnestrovie)-
 # Tiraspol will go back to winter time on October 30, 2011.
 # News from Moldova (in russian):
-# 
 # http://ru.publika.md/link_317061.html
-# 
 
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -1777,8 +1789,8 @@ Zone	Europe/Chisinau	1:55:20 -	LMT	1880
 # more precise 0:09:21.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
-			0:09:21	-	PMT	1911 Mar 11    # Paris Mean Time
-			0:00	France	WE%sT	1945 Sep 16 3:00
+			0:09:21	-	PMT	1911 Mar 11 # Paris Mean Time
+			0:00	France	WE%sT	1945 Sep 16  3:00
 			1:00	France	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1822,8 +1834,8 @@ Zone	Europe/Monaco	0:29:32 -	LMT	1891 Mar 15
 # was not until 1866 when they were all required by law to observe
 # Amsterdam mean time.
 
-# The data before 1945 are taken from
-# .
+# The data entries before 1945 are taken from
+# http://www.phys.uu.nl/~vgent/wettijd/wettijd.htm
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Neth	1916	only	-	May	 1	0:00	1:00	NST	# Netherlands Summer Time
@@ -1854,8 +1866,8 @@ Rule	Neth	1945	only	-	Sep	16	2:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Amsterdam	0:19:32 -	LMT	1835
 			0:19:32	Neth	%s	1937 Jul  1
-			0:20	Neth	NE%sT	1940 May 16 0:00 # Dutch Time
-			1:00	C-Eur	CE%sT	1945 Apr  2 2:00
+			0:20	Neth	NE%sT	1940 May 16  0:00 # Dutch Time
+			1:00	C-Eur	CE%sT	1945 Apr  2  2:00
 			1:00	Neth	CE%sT	1977
 			1:00	EU	CE%sT
 
@@ -1885,14 +1897,14 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
 # time they were declared as parts of Norway.  Svalbard was declared
 # as a part of Norway by law of 1925-07-17 no 11, section 4 and Jan
 # Mayen by law of 1930-02-27 no 2, section 2. (From
-# http://www.lovdata.no/all/nl-19250717-011.html and
-# http://www.lovdata.no/all/nl-19300227-002.html).  The law/regulation
+#  and
+# ).  The law/regulation
 # for normal/standard time in Norway is from 1894-06-29 no 1 (came
 # into operation on 1895-01-01) and Svalbard/Jan Mayen seem to be a
 # part of this law since 1925/1930. (From
-# http://www.lovdata.no/all/nl-18940629-001.html ) I have not been
+# ) I have not been
 # able to find if Jan Mayen used a different time zone (e.g. -0100)
-# before 1930. Jan Mayen has only been "inhabitated" since 1921 by
+# before 1930. Jan Mayen has only been "inhabited" since 1921 by
 # Norwegian meteorologists and maybe used the same time as Norway ever
 # since 1921.  Svalbard (Arctic/Longyearbyen) has been inhabited since
 # before 1895, and therefore probably changed the local time somewhere
@@ -1907,7 +1919,7 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
 #  says that the meteorologists
 # burned down their station in 1940 and left the island, but returned in
 # 1941 with a small Norwegian garrison and continued operations despite
-# frequent air ttacks from Germans.  In 1943 the Americans established a
+# frequent air attacks from Germans.  In 1943 the Americans established a
 # radiolocating station on the island, called "Atlantic City".  Possibly
 # the UT offset changed during the war, but I think it unlikely that
 # Jan Mayen used German daylight-saving rules.
@@ -1918,7 +1930,7 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
 #  says that the Germans were
 # expelled on 1942-05-14.  However, small parties of Germans did return,
 # and according to Wilhelm Dege's book "War North of 80" (1954)
-# 
+# http://www.ucalgary.ca/UofC/departments/UP/1-55238/1-55238-110-2.html
 # the German armed forces at the Svalbard weather station code-named
 # Haudegen did not surrender to the Allies until September 1945.
 #
@@ -1927,6 +1939,10 @@ Zone	Europe/Oslo	0:43:00 -	LMT	1895 Jan  1
 Link	Europe/Oslo	Arctic/Longyearbyen
 
 # Poland
+
+# The 1919 dates and times can be found in Tygodnik Urzędowy nr 1 (1919-03-20),
+#  pp 1-2.
+
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Poland	1918	1919	-	Sep	16	2:00s	0	-
 Rule	Poland	1919	only	-	Apr	15	2:00s	1:00	S
@@ -1937,9 +1953,9 @@ Rule	Poland	1944	only	-	Oct	 4	2:00	0	-
 Rule	Poland	1945	only	-	Apr	29	0:00	1:00	S
 Rule	Poland	1945	only	-	Nov	 1	0:00	0	-
 # For 1946 on the source is Kazimierz Borkowski,
-# Torun Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
-# 
-# Thanks to Przemyslaw Augustyniak (2005-05-28) for this reference.
+# Toruń Center for Astronomy, Dept. of Radio Astronomy, Nicolaus Copernicus U.,
+# http://www.astro.uni.torun.pl/~kb/Artykuly/U-PA/Czas2.htm#tth_tAb1
+# Thanks to Przemysław Augustyniak (2005-05-28) for this reference.
 # He also gives these further references:
 # Mon Pol nr 13, poz 162 (1995) 
 # Druk nr 2180 (2003) 
@@ -1959,10 +1975,10 @@ Rule	Poland	1961	1964	-	May	lastSun	1:00s	1:00	S
 Rule	Poland	1962	1964	-	Sep	lastSun	1:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Warsaw	1:24:00 -	LMT	1880
-			1:24:00	-	WMT	1915 Aug  5   # Warsaw Mean Time
-			1:00	C-Eur	CE%sT	1918 Sep 16 3:00
+			1:24:00	-	WMT	1915 Aug  5 # Warsaw Mean Time
+			1:00	C-Eur	CE%sT	1918 Sep 16  3:00
 			2:00	Poland	EE%sT	1922 Jun
-			1:00	Poland	CE%sT	1940 Jun 23 2:00
+			1:00	Poland	CE%sT	1940 Jun 23  2:00
 			1:00	C-Eur	CE%sT	1944 Oct
 			1:00	Poland	CE%sT	1977
 			1:00	W-Eur	CE%sT	1988
@@ -1970,6 +1986,14 @@ Zone	Europe/Warsaw	1:24:00 -	LMT	1880
 
 # Portugal
 #
+# From Paul Eggert (2014-08-11), after a heads-up from Stephen Colebourne:
+# According to a Portuguese decree (1911-05-26)
+# http://dre.pt/pdf1sdip/1911/05/12500/23132313.pdf
+# Lisbon was at -0:36:44.68, but switched to GMT on 1912-01-01 at 00:00.
+# Round the old offset to -0:36:45.  This agrees with Willett but disagrees
+# with Shanks, who says the transition occurred on 1911-05-24 at 00:00 for
+# Europe/Lisbon, Atlantic/Azores, and Atlantic/Madeira.
+#
 # From Rui Pedro Salgueiro (1992-11-12):
 # Portugal has recently (September, 27) changed timezone
 # (from WET to MET or CET) to harmonize with EEC.
@@ -2049,35 +2073,34 @@ Rule	Port	1979	1982	-	Sep	lastSun	 1:00s	0	-
 Rule	Port	1980	only	-	Mar	lastSun	 0:00s	1:00	S
 Rule	Port	1981	1982	-	Mar	lastSun	 1:00s	1:00	S
 Rule	Port	1983	only	-	Mar	lastSun	 2:00s	1:00	S
+#
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Shanks & Pottenger say the transition from LMT to WET occurred 1911-05-24;
-# Willett says 1912-01-01.  Go with Willett.
-Zone	Europe/Lisbon	-0:36:32 -	LMT	1884
-			-0:36:32 -	LMT	1912 Jan  1  # Lisbon Mean Time
-			 0:00	Port	WE%sT	1966 Apr  3 2:00
-			 1:00	-	CET	1976 Sep 26 1:00
-			 0:00	Port	WE%sT	1983 Sep 25 1:00s
-			 0:00	W-Eur	WE%sT	1992 Sep 27 1:00s
-			 1:00	EU	CE%sT	1996 Mar 31 1:00u
+Zone	Europe/Lisbon	-0:36:45 -	LMT	1884
+			-0:36:45 -	LMT	1912 Jan  1 # Lisbon Mean Time
+			 0:00	Port	WE%sT	1966 Apr  3  2:00
+			 1:00	-	CET	1976 Sep 26  1:00
+			 0:00	Port	WE%sT	1983 Sep 25  1:00s
+			 0:00	W-Eur	WE%sT	1992 Sep 27  1:00s
+			 1:00	EU	CE%sT	1996 Mar 31  1:00u
 			 0:00	EU	WE%sT
-Zone Atlantic/Azores	-1:42:40 -	LMT	1884		# Ponta Delgada
-			-1:54:32 -	HMT	1911 May 24  # Horta Mean Time
-			-2:00	Port	AZO%sT	1966 Apr  3 2:00 # Azores Time
-			-1:00	Port	AZO%sT	1983 Sep 25 1:00s
-			-1:00	W-Eur	AZO%sT	1992 Sep 27 1:00s
-			 0:00	EU	WE%sT	1993 Mar 28 1:00u
+Zone Atlantic/Azores	-1:42:40 -	LMT	1884        # Ponta Delgada
+			-1:54:32 -	HMT	1912 Jan  1 # Horta Mean Time
+			-2:00	Port	AZO%sT	1966 Apr  3  2:00  # Azores Time
+			-1:00	Port	AZO%sT	1983 Sep 25  1:00s
+			-1:00	W-Eur	AZO%sT	1992 Sep 27  1:00s
+			 0:00	EU	WE%sT	1993 Mar 28  1:00u
 			-1:00	EU	AZO%sT
-Zone Atlantic/Madeira	-1:07:36 -	LMT	1884		# Funchal
-			-1:07:36 -	FMT	1911 May 24  # Funchal Mean Time
-			-1:00	Port	MAD%sT	1966 Apr  3 2:00 # Madeira Time
-			 0:00	Port	WE%sT	1983 Sep 25 1:00s
+Zone Atlantic/Madeira	-1:07:36 -	LMT	1884        # Funchal
+			-1:07:36 -	FMT	1912 Jan  1 # Funchal Mean Time
+			-1:00	Port	MAD%sT	1966 Apr  3  2:00 # Madeira Time
+			 0:00	Port	WE%sT	1983 Sep 25  1:00s
 			 0:00	EU	WE%sT
 
 # Romania
 #
 # From Paul Eggert (1999-10-07):
-# 
-# Nine O'clock (1998-10-23) reports that the switch occurred at
+# Nine O'clock 
+# (1998-10-23) reports that the switch occurred at
 # 04:00 local time in fall 1998.  For lack of better info,
 # assume that Romania and Moldova switched to EU rules in 1997,
 # the same year as Bulgaria.
@@ -2094,32 +2117,28 @@ Rule	Romania	1991	1993	-	Mar	lastSun	 0:00s	1:00	S
 Rule	Romania	1991	1993	-	Sep	lastSun	 0:00s	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
-			1:44:24	-	BMT	1931 Jul 24	# Bucharest MT
-			2:00	Romania	EE%sT	1981 Mar 29 2:00s
+			1:44:24	-	BMT	1931 Jul 24 # Bucharest MT
+			2:00	Romania	EE%sT	1981 Mar 29  2:00s
 			2:00	C-Eur	EE%sT	1991
 			2:00	Romania	EE%sT	1994
 			2:00	E-Eur	EE%sT	1997
 			2:00	EU	EE%sT
 
+
 # Russia
 
 # From Alexander Krivenyshev (2011-09-15):
 # Based on last Russian Government Decree # 725 on August 31, 2011
 # (Government document
-# 
 # http://www.government.ru/gov/results/16355/print/
-# 
 # in Russian)
 # there are few corrections have to be made for some Russian time zones...
 # All updated Russian Time Zones were placed in table and translated to English
 # by WorldTimeZone.com at the link below:
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_russia36.htm
-# 
 
 # From Sanjeev Gupta (2011-09-27):
 # Scans of [Decree #23 of January 8, 1992] are available at:
-# 
 # http://government.consultant.ru/page.aspx?1223966
 # They are in Cyrillic letters (presumably Russian).
 
@@ -2128,16 +2147,12 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
 # changed in September 2011:
 #
 # One source is
-# < a href="http://government.ru/gov/results/16355/>
 # http://government.ru/gov/results/16355/
-# 
 # which, according to translate.google.com, begins "Decree of August 31,
 # 2011 No 725" and contains no other dates or "effective date" information.
 #
 # Another source is
-# 
 # http://www.rg.ru/2011/09/06/chas-zona-dok.html
-# 
 # which, according to translate.google.com, begins "Resolution of the
 # Government of the Russian Federation on August 31, 2011 N 725" and also
 # contains "Date first official publication: September 6, 2011 Posted on:
@@ -2145,28 +2160,45 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
 # does not contain any "effective date" information.
 #
 # Another source is
-# 
 # http://en.wikipedia.org/wiki/Oymyakonsky_District#cite_note-RuTime-7
-# 
 # which, in note 8, contains "Resolution #725 of August 31, 2011...
 # Effective as of after 7 days following the day of the official publication"
 # but which does not contain any reference to September 6, 2011.
 #
 # The Wikipedia article refers to
-# 
 # http://base.consultant.ru/cons/cgi/online.cgi?req=doc;base=LAW;n=118896
-# 
 # which seems to copy the text of the government.ru page.
 #
 # Tobias Conradi combines Wikipedia's
 # "as of after 7 days following the day of the official publication"
-# with www.rg.ru's "Date of first official publication: September 6, 2011" to get
-# September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias Conradi notes).
+# with www.rg.ru's "Date of first official publication: September 6, 2011" to
+# get September 13, 2011 as the cutover date (unusually, a Tuesday, as Tobias
+# Conradi notes).
 #
 # None of the sources indicates a time of day for changing clocks.
 #
 # Go with 2011-09-13 0:00s.
 
+# From Alexander Krivenyshev (2014-07-01):
+# According to the Russian news (ITAR-TASS News Agency)
+# http://en.itar-tass.com/russia/738562
+# the State Duma has approved ... the draft bill on returning to
+# winter time standard and return Russia 11 time zones.  The new
+# regulations will come into effect on October 26, 2014 at 02:00 ...
+# http://asozd2.duma.gov.ru/main.nsf/%28Spravka%29?OpenAgent&RN=431985-6&02
+# Here is a link where we put together table (based on approved Bill N
+# 431985-6) with proposed 11 Russian time zones and corresponding
+# areas/cities/administrative centers in the Russian Federation (in English):
+# http://www.worldtimezone.com/dst_news/dst_news_russia65.html
+#
+# From Alexander Krivenyshev (2014-07-22):
+# Putin signed the Federal Law 431985-6 ... (in Russian)
+# http://itar-tass.com/obschestvo/1333711
+# http://www.pravo.gov.ru:8080/page.aspx?111660
+# http://www.kremlin.ru/acts/46279
+# From October 26, 2014 the new Russian time zone map will looks like this:
+# http://www.worldtimezone.com/dst_news/dst_news_russia-map-2014-07.html
+
 # From Paul Eggert (2006-03-22):
 # Except for Moscow after 1919-07-01, I invented the time zone abbreviations.
 # Moscow time zone abbreviations after 1919-07-01, and Moscow rules after 1991,
@@ -2193,9 +2225,9 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
 #
 # For Grozny, Chechnya, we have the following story from
 # John Daniszewski, "Scavengers in the Rubble", Los Angeles Times (2001-02-07):
-# News--often false--is spread by word of mouth.  A rumor that it was
+# News - often false - is spread by word of mouth.  A rumor that it was
 # time to move the clocks back put this whole city out of sync with
-# the rest of Russia for two weeks--even soldiers stationed here began
+# the rest of Russia for two weeks - even soldiers stationed here began
 # enforcing curfew at the wrong time.
 #
 # From Gwillim Law (2001-06-05):
@@ -2206,107 +2238,265 @@ Zone Europe/Bucharest	1:44:24 -	LMT	1891 Oct
 # since September 1997....  Although the Kuril Islands are
 # administratively part of Sakhalin oblast', they appear to have
 # remained on UTC+11 along with Magadan.
-#
+
+# From Tim Parenti (2014-07-06):
+# The comments detailing the coverage of each Russian zone are meant to assist
+# with maintenance only and represent our best guesses as to which regions
+# are covered by each zone.  They are not meant to be taken as an authoritative
+# listing.  The region codes listed come from
+# http://en.wikipedia.org/w/?title=Federal_subjects_of_Russia&oldid=611810498
+# and are used for convenience only; no guarantees are made regarding their
+# future stability.  ISO 3166-2:RU codes are also listed for first-level
+# divisions where available.
+
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-#
-# Kaliningradskaya oblast'.
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Kaliningrad covers...
+# 39	RU-KGD	Kaliningrad Oblast
+
 Zone Europe/Kaliningrad	 1:22:00 -	LMT	1893 Apr
 			 1:00	C-Eur	CE%sT	1945
 			 2:00	Poland	CE%sT	1946
-			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			 2:00	Russia	EE%sT	2011 Mar 27 2:00s
-			 3:00	-	FET # Further-eastern European Time
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	2011 Mar 27  2:00s
+			 3:00	-	FET	2014 Oct 26  2:00s
+			 2:00	-	EET
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Europe/Moscow covers...
+# 01	RU-AD	Adygea, Republic of
+# 05	RU-DA	Dagestan, Republic of
+# 06	RU-IN	Ingushetia, Republic of
+# 07	RU-KB	Kabardino-Balkar Republic
+# 08	RU-KL	Kalmykia, Republic of
+# 09	RU-KC	Karachay-Cherkess Republic
+# 10	RU-KR	Karelia, Republic of
+# 11	RU-KO	Komi Republic
+# 12	RU-ME	Mari El Republic
+# 13	RU-MO	Mordovia, Republic of
+# 15	RU-SE	North Ossetia-Alania, Republic of
+# 16	RU-TA	Tatarstan, Republic of
+# 20	RU-CE	Chechen Republic
+# 21	RU-CU	Chuvash Republic
+# 23	RU-KDA	Krasnodar Krai
+# 26	RU-STA	Stavropol Krai
+# 29	RU-ARK	Arkhangelsk Oblast
+# 31	RU-BEL	Belgorod Oblast
+# 32	RU-BRY	Bryansk Oblast
+# 33	RU-VLA	Vladimir Oblast
+# 35	RU-VLG	Vologda Oblast
+# 36	RU-VOR	Voronezh Oblast
+# 37	RU-IVA	Ivanovo Oblast
+# 40	RU-KLU	Kaluga Oblast
+# 44	RU-KOS	Kostroma Oblast
+# 46	RU-KRS	Kursk Oblast
+# 47	RU-LEN	Leningrad Oblast
+# 48	RU-LIP	Lipetsk Oblast
+# 50	RU-MOS	Moscow Oblast
+# 51	RU-MUR	Murmansk Oblast
+# 52	RU-NIZ	Nizhny Novgorod Oblast
+# 53	RU-NGR	Novgorod Oblast
+# 57	RU-ORL	Oryol Oblast
+# 58	RU-PNZ	Penza Oblast
+# 60	RU-PSK	Pskov Oblast
+# 61	RU-ROS	Rostov Oblast
+# 62	RU-RYA	Ryazan Oblast
+# 67	RU-SMO	Smolensk Oblast
+# 68	RU-TAM	Tambov Oblast
+# 69	RU-TVE	Tver Oblast
+# 71	RU-TUL	Tula Oblast
+# 73	RU-ULY	Ulyanovsk Oblast
+# 76	RU-YAR	Yaroslavl Oblast
+# 77	RU-MOW	Moscow
+# 78	RU-SPE	Saint Petersburg
+# 83	RU-NEN	Nenets Autonomous Okrug
+
+# From Vladimir Karpinsky (2014-07-08):
+# LMT in Moscow (before Jul 3, 1916) is 2:30:17, that was defined by Moscow
+# Observatory (coordinates: 55 deg. 45'29.70", 37 deg. 34'05.30")....
+# LMT in Moscow since Jul 3, 1916 is 2:31:01 as a result of new standard.
+# (The info is from the book by Byalokoz ... p. 18.)
+# The time in St. Petersburg as capital of Russia was defined by
+# Pulkov observatory, near St. Petersburg.  In 1916 LMT Moscow
+# was synchronized with LMT St. Petersburg (+30 minutes), (Pulkov observatory
+# coordinates: 59 deg. 46'18.70", 30 deg. 19'40.70") so 30 deg. 19'40.70" >
+# 2h01m18.7s = 2:01:19.  LMT Moscow = LMT St.Petersburg + 30m 2:01:19 + 0:30 =
+# 2:31:19 ...
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Adygeya, Arkhangel'skaya oblast',
-# Belgorodskaya oblast', Bryanskaya oblast', Vladimirskaya oblast',
-# Vologodskaya oblast', Voronezhskaya oblast',
-# Respublika Dagestan, Ivanovskaya oblast', Respublika Ingushetiya,
-# Kabarbino-Balkarskaya Respublika, Respublika Kalmykiya,
-# Kalyzhskaya oblast', Respublika Karachaevo-Cherkessiya,
-# Respublika Kareliya, Respublika Komi,
-# Kostromskaya oblast', Krasnodarskij kraj, Kurskaya oblast',
-# Leningradskaya oblast', Lipetskaya oblast', Respublika Marij El,
-# Respublika Mordoviya, Moskva, Moskovskaya oblast',
-# Murmanskaya oblast', Nenetskij avtonomnyj okrug,
-# Nizhegorodskaya oblast', Novgorodskaya oblast', Orlovskaya oblast',
-# Penzenskaya oblast', Pskovskaya oblast', Rostovskaya oblast',
-# Ryazanskaya oblast', Sankt-Peterburg,
-# Respublika Severnaya Osetiya, Smolenskaya oblast',
-# Stavropol'skij kraj, Tambovskaya oblast', Respublika Tatarstan,
-# Tverskaya oblast', Tyl'skaya oblast', Ul'yanovskaya oblast',
-# Chechenskaya Respublika, Chuvashskaya oblast',
-# Yaroslavskaya oblast'
-Zone Europe/Moscow	 2:30:20 -	LMT	1880
-			 2:30	-	MMT	1916 Jul  3 # Moscow Mean Time
-			 2:30:48 Russia	%s	1919 Jul  1 2:00
+# From Paul Eggert (2014-07-08):
+# Milne does not list Moscow, but suggests that its time might be listed in
+# Résumés mensuels et annuels des observations météorologiques (1895).
+# Presumably this is OCLC 85825704, a journal published with parallel text in
+# Russian and French.  This source has not been located; go with Karpinsky.
+
+Zone Europe/Moscow	 2:30:17 -	LMT	1880
+			 2:30:17 -	MMT	1916 Jul  3 # Moscow Mean Time
+			 2:31:19 Russia	%s	1919 Jul  1  2:00
+			 3:00	Russia	%s	1921 Oct
 			 3:00	Russia	MSK/MSD	1922 Oct
 			 2:00	-	EET	1930 Jun 21
-			 3:00	Russia	MSK/MSD	1991 Mar 31 2:00s
-			 2:00	Russia	EE%sT	1992 Jan 19 2:00s
-			 3:00	Russia	MSK/MSD	2011 Mar 27 2:00s
-			 4:00	-	MSK
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	1992 Jan 19  2:00s
+			 3:00	Russia	MSK/MSD	2011 Mar 27  2:00s
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Simferopol covers...
+# **	****	Crimea, Republic of
+# **	****	Sevastopol
+
+Zone Europe/Simferopol	 2:16:24 -	LMT	1880
+			 2:16	-	SMT	1924 May  2 # Simferopol Mean T
+			 2:00	-	EET	1930 Jun 21
+			 3:00	-	MSK	1941 Nov
+			 1:00	C-Eur	CE%sT	1944 Apr 13
+			 3:00	Russia	MSK/MSD	1990
+			 3:00	-	MSK	1990 Jul  1  2:00
+			 2:00	-	EET	1992
+# Central Crimea used Moscow time 1994/1997.
 #
-# Astrakhanskaya oblast', Kirovskaya oblast', Saratovskaya oblast',
-# Volgogradskaya oblast'.  Shanks & Pottenger say Kirov is still at +0400
-# but Wikipedia (2006-05-09) says +0300.  Perhaps it switched after the
-# others?  But we have no data.
+# From Paul Eggert (2006-03-22):
+# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
+# from Kiev to Moscow time sometime after the January 1994 elections.
+# Shanks (1999) says "date of change uncertain", but implies that it happened
+# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
+# 1994-09-25 03:00, but that can't be right.  For now, guess it
+# changed in May.
+			 2:00	E-Eur	EE%sT	1994 May
+# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
+			 3:00	E-Eur	MSK/MSD	1996 Mar 31  3:00s
+			 3:00	1:00	MSD	1996 Oct 27  3:00s
+# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
+# Assume it happened in March by not changing the clocks.
+			 3:00	Russia	MSK/MSD	1997
+			 3:00	-	MSK	1997 Mar lastSun  1:00u
+# From Alexander Krivenyshev (2014-03-17):
+# time change at 2:00 (2am) on March 30, 2014
+# http://vz.ru/news/2014/3/17/677464.html
+# From Paul Eggert (2014-03-30):
+# Simferopol and Sevastopol reportedly changed their central town clocks
+# late the previous day, but this appears to have been ceremonial
+# and the discrepancies are small enough to not worry about.
+			 2:00	EU	EE%sT	2014 Mar 30  2:00
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03):
+# Europe/Volgograd covers...
+# 30	RU-AST	Astrakhan Oblast
+# 34	RU-VGG	Volgograd Oblast
+# 43	RU-KIR	Kirov Oblast
+# 64	RU-SAR	Saratov Oblast
+
+# From Paul Eggert (2006-05-09):
+# Shanks & Pottenger say Kirov is still at +0400 but Wikipedia says +0300.
+# Perhaps it switched after the others?  But we have no data.
+
 Zone Europe/Volgograd	 2:57:40 -	LMT	1920 Jan  3
 			 3:00	-	TSAT	1925 Apr  6 # Tsaritsyn Time
 			 3:00	-	STAT	1930 Jun 21 # Stalingrad Time
 			 4:00	-	STAT	1961 Nov 11
-			 4:00	Russia	VOL%sT	1989 Mar 26 2:00s # Volgograd T
-			 3:00	Russia	VOL%sT	1991 Mar 31 2:00s
-			 4:00	-	VOLT	1992 Mar 29 2:00s
-			 3:00	Russia	VOL%sT	2011 Mar 27 2:00s
-			 4:00	-	VOLT
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Samarskaya oblast', Udmyrtskaya respublika
-Zone Europe/Samara	 3:20:36 -	LMT	1919 Jul  1 2:00
+			 4:00	Russia	VOL%sT	1989 Mar 26  2:00s # Volgograd T
+			 3:00	Russia	VOL%sT	1991 Mar 31  2:00s
+			 4:00	-	VOLT	1992 Mar 29  2:00s
+			 3:00	Russia	MSK	2011 Mar 27  2:00s
+			 4:00	-	MSK	2014 Oct 26  2:00s
+			 3:00	-	MSK
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Europe/Samara covers...
+# 18	RU-UD	Udmurt Republic
+# 63	RU-SAM	Samara Oblast
+
+# Byalokoz 1919 says Samara was 3:20:20.
+
+Zone Europe/Samara	 3:20:20 -	LMT	1919 Jul  1  2:00
 			 3:00	-	SAMT	1930 Jun 21
 			 4:00	-	SAMT	1935 Jan 27
-			 4:00	Russia	KUY%sT	1989 Mar 26 2:00s # Kuybyshev
-			 3:00	Russia	KUY%sT	1991 Mar 31 2:00s
-			 2:00	Russia	KUY%sT	1991 Sep 29 2:00s
-			 3:00	-	KUYT	1991 Oct 20 3:00
-			 4:00	Russia	SAM%sT	2010 Mar 28 2:00s # Samara Time
-			 3:00	Russia	SAM%sT	2011 Mar 27 2:00s
+			 4:00	Russia	KUY%sT	1989 Mar 26  2:00s # Kuybyshev
+			 3:00	Russia	MSK/MSD	1991 Mar 31  2:00s
+			 2:00	Russia	EE%sT	1991 Sep 29  2:00s
+			 3:00	-	KUYT	1991 Oct 20  3:00
+			 4:00	Russia	SAM%sT	2010 Mar 28  2:00s # Samara Time
+			 3:00	Russia	SAM%sT	2011 Mar 27  2:00s
 			 4:00	-	SAMT
 
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Yekaterinburg covers...
+# 02	RU-BA	Bashkortostan, Republic of
+# 90	RU-PER	Perm Krai
+# 45	RU-KGN	Kurgan Oblast
+# 56	RU-ORE	Orenburg Oblast
+# 66	RU-SVE	Sverdlovsk Oblast
+# 72	RU-TYU	Tyumen Oblast
+# 74	RU-CHE	Chelyabinsk Oblast
+# 86	RU-KHM	Khanty-Mansi Autonomous Okrug - Yugra
+# 89	RU-YAN	Yamalo-Nenets Autonomous Okrug
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Bashkortostan, Komi-Permyatskij avtonomnyj okrug,
-# Kurganskaya oblast', Orenburgskaya oblast', Permskaya oblast',
-# Sverdlovskaya oblast', Tyumenskaya oblast',
-# Khanty-Manskijskij avtonomnyj okrug, Chelyabinskaya oblast',
-# Yamalo-Nenetskij avtonomnyj okrug.
-Zone Asia/Yekaterinburg	 4:02:24 -	LMT	1919 Jul 15 4:00
+# Note: Effective 2005-12-01, (59) Perm Oblast and (81) Komi-Permyak
+# Autonomous Okrug merged to form (90, RU-PER) Perm Krai.
+
+# Milne says Yekaterinburg was 4:02:32.9; round to nearest.
+# Byalokoz 1919 says its provincial time was based on Perm, at 3:45:05.
+# Assume it switched on 1916-07-03, the time of the new standard.
+# The 1919 and 1930 transitions are from Shanks.
+
+Zone Asia/Yekaterinburg	 4:02:33 -	LMT	1916 Jul  3
+			 3:45:05 -	PMT	1919 Jul 15  4:00
 			 4:00	-	SVET	1930 Jun 21 # Sverdlovsk Time
-			 5:00	Russia	SVE%sT	1991 Mar 31 2:00s
-			 4:00	Russia	SVE%sT	1992 Jan 19 2:00s
-			 5:00	Russia	YEK%sT	2011 Mar 27 2:00s
-			 6:00	-	YEKT	# Yekaterinburg Time
-#
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Altaj, Altajskij kraj, Omskaya oblast'.
-Zone Asia/Omsk		 4:53:36 -	LMT	1919 Nov 14
-			 5:00	-	OMST	1930 Jun 21 # Omsk TIme
-			 6:00	Russia	OMS%sT	1991 Mar 31 2:00s
-			 5:00	Russia	OMS%sT	1992 Jan 19 2:00s
-			 6:00	Russia	OMS%sT	2011 Mar 27 2:00s
-			 7:00	-	OMST
-#
+			 5:00	Russia	SVE%sT	1991 Mar 31  2:00s
+			 4:00	Russia	SVE%sT	1992 Jan 19  2:00s
+			 5:00	Russia	YEK%sT	2011 Mar 27  2:00s
+			 6:00	-	YEKT	2014 Oct 26  2:00s
+			 5:00	-	YEKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Omsk covers...
+# 04	RU-AL	Altai Republic
+# 22	RU-ALT	Altai Krai
+# 55	RU-OMS	Omsk Oblast
+
+# Byalokoz 1919 says Omsk was 4:53:30.
+
+Zone Asia/Omsk		 4:53:30 -	LMT	1919 Nov 14
+			 5:00	-	OMST	1930 Jun 21 # Omsk Time
+			 6:00	Russia	OMS%sT	1991 Mar 31  2:00s
+			 5:00	Russia	OMS%sT	1992 Jan 19  2:00s
+			 6:00	Russia	OMS%sT	2011 Mar 27  2:00s
+			 7:00	-	OMST	2014 Oct 26  2:00s
+			 6:00	-	OMST
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Novosibirsk covers...
+# 54	RU-NVS	Novosibirsk Oblast
+# 70	RU-TOM	Tomsk Oblast
+
 # From Paul Eggert (2006-08-19): I'm guessing about Tomsk here; it's
 # not clear when it switched from +7 to +6.
-# Novosibirskaya oblast', Tomskaya oblast'.
-Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
+
+Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14  6:00
 			 6:00	-	NOVT	1930 Jun 21 # Novosibirsk Time
-			 7:00	Russia	NOV%sT	1991 Mar 31 2:00s
-			 6:00	Russia	NOV%sT	1992 Jan 19 2:00s
+			 7:00	Russia	NOV%sT	1991 Mar 31  2:00s
+			 6:00	Russia	NOV%sT	1992 Jan 19  2:00s
 			 7:00	Russia	NOV%sT	1993 May 23 # say Shanks & P.
-			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
-			 7:00	-	NOVT
+			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s
+			 7:00	-	NOVT	2014 Oct 26  2:00s
+			 6:00	-	NOVT
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Novokuznetsk covers...
+# 42	RU-KEM	Kemerovo Oblast
 
 # From Alexander Krivenyshev (2009-10-13):
 # Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on
@@ -2319,14 +2509,10 @@ Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
 # time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
 #
 # Russian Government web site (Russian language)
-# 
 # http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archive/2009/09/14/991633.htm
-# 
 # or Russian-English translation by WorldTimeZone.com with reference
 # map to local region and new Russia Time Zone map after March 28, 2010
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_russia03.html
-# 
 #
 # Thus, when Russia will switch to DST on the night of March 28, 2010
 # Kemerovo region (Kemerovo oblast') will not change the clock.
@@ -2334,152 +2520,319 @@ Zone Asia/Novosibirsk	 5:31:40 -	LMT	1919 Dec 14 6:00
 # As a result, Kemerovo oblast' will be in the same time zone as
 # Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic.
 
+# From Tim Parenti (2014-07-02), per Alexander Krivenyshev (2014-07-02):
+# The Kemerovo region will remain at UTC+7 through the 2014-10-26 change, thus
+# realigning itself with KRAT.
+
 Zone Asia/Novokuznetsk	 5:48:48 -	NMT	1920 Jan  6
 			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
-			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
-			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
-			 7:00	Russia	KRA%sT	2010 Mar 28 2:00s
-			 6:00	Russia	NOV%sT	2011 Mar 27 2:00s
-			 7:00	-	NOVT # Novosibirsk/Novokuznetsk Time
+			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
+			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
+			 7:00	Russia	KRA%sT	2010 Mar 28  2:00s
+			 6:00	Russia	NOV%sT	2011 Mar 27  2:00s # Novosibirsk
+			 7:00	-	NOVT	2014 Oct 26  2:00s
+			 7:00	-	KRAT	# Krasnoyarsk Time
 
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Krasnoyarsk covers...
+# 17	RU-TY	Tuva Republic
+# 19	RU-KK	Khakassia, Republic of
+# 24	RU-KYA	Krasnoyarsk Krai
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Krasnoyarskij kraj,
-# Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug,
-# Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug.
-Zone Asia/Krasnoyarsk	 6:11:20 -	LMT	1920 Jan  6
+# Note: Effective 2007-01-01, (88) Evenk Autonomous Okrug and (84) Taymyr
+# Autonomous Okrug were merged into (24, RU-KYA) Krasnoyarsk Krai.
+
+# Byalokoz 1919 says Krasnoyarsk was 6:11:26.
+
+Zone Asia/Krasnoyarsk	 6:11:26 -	LMT	1920 Jan  6
 			 6:00	-	KRAT	1930 Jun 21 # Krasnoyarsk Time
-			 7:00	Russia	KRA%sT	1991 Mar 31 2:00s
-			 6:00	Russia	KRA%sT	1992 Jan 19 2:00s
-			 7:00	Russia	KRA%sT	2011 Mar 27 2:00s
-			 8:00	-	KRAT
+			 7:00	Russia	KRA%sT	1991 Mar 31  2:00s
+			 6:00	Russia	KRA%sT	1992 Jan 19  2:00s
+			 7:00	Russia	KRA%sT	2011 Mar 27  2:00s
+			 8:00	-	KRAT	2014 Oct 26  2:00s
+			 7:00	-	KRAT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Irkutsk covers...
+# 03	RU-BU	Buryatia, Republic of
+# 38	RU-IRK	Irkutsk Oblast
 #
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Respublika Buryatiya, Irkutskaya oblast',
-# Ust'-Ordynskij Buryatskij avtonomnyj okrug.
-Zone Asia/Irkutsk	 6:57:20 -	LMT	1880
-			 6:57:20 -	IMT	1920 Jan 25 # Irkutsk Mean Time
+# Note: Effective 2008-01-01, (85) Ust-Orda Buryat Autonomous Okrug was
+# merged into (38, RU-IRK) Irkutsk Oblast.
+
+# Milne 1899 says Irkutsk was 6:57:15.
+# Byalokoz 1919 says Irkutsk was 6:57:05.
+# Go with Byalokoz.
+
+Zone Asia/Irkutsk	 6:57:05 -	LMT	1880
+			 6:57:05 -	IMT	1920 Jan 25 # Irkutsk Mean Time
 			 7:00	-	IRKT	1930 Jun 21 # Irkutsk Time
-			 8:00	Russia	IRK%sT	1991 Mar 31 2:00s
-			 7:00	Russia	IRK%sT	1992 Jan 19 2:00s
-			 8:00	Russia	IRK%sT	2011 Mar 27 2:00s
-			 9:00	-	IRKT
+			 8:00	Russia	IRK%sT	1991 Mar 31  2:00s
+			 7:00	Russia	IRK%sT	1992 Jan 19  2:00s
+			 8:00	Russia	IRK%sT	2011 Mar 27  2:00s
+			 9:00	-	IRKT	2014 Oct 26  2:00s
+			 8:00	-	IRKT
+
+
+# From Tim Parenti (2014-07-06):
+# Asia/Chita covers...
+# 92	RU-ZAB	Zabaykalsky Krai
 #
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Aginskij Buryatskij avtonomnyj okrug, Amurskaya oblast',
-# [parts of] Respublika Sakha (Yakutiya), Chitinskaya oblast'.
+# Note: Effective 2008-03-01, (75) Chita Oblast and (80) Agin-Buryat
+# Autonomous Okrug merged to form (92, RU-ZAB) Zabaykalsky Krai.
 
-# From Oscar van Vlijmen (2009-11-29):
-# ...some regions of [Russia] were merged with others since 2005...
-# Some names were changed, no big deal, except for one instance: a new name.
-# YAK/YAKST: UTC+9 Zabajkal'skij kraj.
-
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Aldanskij, Amginskij, Anabarskij,
-# Verkhnevilyujskij, Vilyujskij, Gornyj,
-# Zhiganskij, Kobyajskij, Lenskij, Megino-Kangalasskij, Mirninskij,
-# Namskij, Nyurbinskij, Olenyokskij, Olyokminskij,
-# Suntarskij, Tattinskij, Ust'-Aldanskij, Khangalasskij,
-# Churapchinskij, Eveno-Bytantajskij Natsional'nij.
-
-Zone Asia/Yakutsk	 8:38:40 -	LMT	1919 Dec 15
+Zone Asia/Chita	 7:33:52 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
-			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
-			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
-			 9:00	Russia	YAK%sT	2011 Mar 27 2:00s
-			 10:00	-	YAKT
-#
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Evrejskaya avtonomnaya oblast', Khabarovskij kraj, Primorskij kraj,
-# [parts of] Respublika Sakha (Yakutiya).
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
+			 9:00	Russia	YAK%sT	2011 Mar 27  2:00s
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 8:00	-	IRKT
 
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Bulunskij, Verkhoyanskij, ... Ust'-Yanskij.
-Zone Asia/Vladivostok	 8:47:44 -	LMT	1922 Nov 15
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Yakutsk covers...
+# 28	RU-AMU	Amur Oblast
+#
+# ...and parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-02	****	Aldansky District
+# 14-04	****	Amginsky District
+# 14-05	****	Anabarsky District
+# 14-06	****	Bulunsky District
+# 14-07	****	Verkhnevilyuysky District
+# 14-10	****	Vilyuysky District
+# 14-11	****	Gorny District
+# 14-12	****	Zhigansky District
+# 14-13	****	Kobyaysky District
+# 14-14	****	Lensky District
+# 14-15	****	Megino-Kangalassky District
+# 14-16	****	Mirninsky District
+# 14-18	****	Namsky District
+# 14-19	****	Neryungrinsky District
+# 14-21	****	Nyurbinsky District
+# 14-23	****	Olenyoksky District
+# 14-24	****	Olyokminsky District
+# 14-26	****	Suntarsky District
+# 14-27	****	Tattinsky District
+# 14-29	****	Ust-Aldansky District
+# 14-32	****	Khangalassky District
+# 14-33	****	Churapchinsky District
+# 14-34	****	Eveno-Bytantaysky National District
+
+# From Tim Parenti (2014-07-03):
+# Our commentary seems to have lost mention of (14-19) Neryungrinsky District.
+# Since the surrounding districts of Sakha are all YAKT, assume this is, too.
+# Also assume its history has been the same as the rest of Asia/Yakutsk.
+
+# Byalokoz 1919 says Yakutsk was 8:38:58.
+
+Zone Asia/Yakutsk	 8:38:58 -	LMT	1919 Dec 15
+			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
+			 9:00	Russia	YAK%sT	2011 Mar 27  2:00s
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 9:00	-	YAKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Vladivostok covers...
+# 25	RU-PRI	Primorsky Krai
+# 27	RU-KHA	Khabarovsk Krai
+# 79	RU-YEV	Jewish Autonomous Oblast
+#
+# ...and parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-09	****	Verkhoyansky District
+# 14-31	****	Ust-Yansky District
+
+# Milne 1899 says Vladivostok was 8:47:33.5.
+# Byalokoz 1919 says Vladivostok was 8:47:31.
+# Go with Byalokoz.
+
+Zone Asia/Vladivostok	 8:47:31 -	LMT	1922 Nov 15
 			 9:00	-	VLAT	1930 Jun 21 # Vladivostok Time
-			10:00	Russia	VLA%sT	1991 Mar 31 2:00s
-			 9:00	Russia	VLA%sST	1992 Jan 19 2:00s
-			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
-			11:00	-	VLAT
+			10:00	Russia	VLA%sT	1991 Mar 31  2:00s
+			 9:00	Russia	VLA%sT	1992 Jan 19  2:00s
+			10:00	Russia	VLA%sT	2011 Mar 27  2:00s
+			11:00	-	VLAT	2014 Oct 26  2:00s
+			10:00	-	VLAT
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Khandyga covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-28	****	Tomponsky District
+# 14-30	****	Ust-Maysky District
 
 # From Arthur David Olson (2012-05-09):
 # Tomponskij and Ust'-Majskij switched from Vladivostok time to Yakutsk time
 # in 2011.
-#
+
 # From Paul Eggert (2012-11-25):
 # Shanks and Pottenger (2003) has Khandyga on Yakutsk time.
 # Make a wild guess that it switched to Vladivostok time in 2004.
 # This transition is no doubt wrong, but we have no better info.
-#
+
 Zone Asia/Khandyga	 9:02:13 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
-			 9:00	Russia	YAK%sT	1991 Mar 31 2:00s
-			 8:00	Russia	YAK%sT	1992 Jan 19 2:00s
+			 9:00	Russia	YAK%sT	1991 Mar 31  2:00s
+			 8:00	Russia	YAK%sT	1992 Jan 19  2:00s
 			 9:00	Russia	YAK%sT	2004
-			10:00	Russia	VLA%sT	2011 Mar 27 2:00s
-			11:00	-	VLAT	2011 Sep 13 0:00s # Decree 725?
-			10:00	-	YAKT
+			10:00	Russia	VLA%sT	2011 Mar 27  2:00s
+			11:00	-	VLAT	2011 Sep 13  0:00s # Decree 725?
+			10:00	-	YAKT	2014 Oct 26  2:00s
+			 9:00	-	YAKT
 
-#
-# Sakhalinskaya oblast'.
-# The Zone name should be Yuzhno-Sakhalinsk, but that's too long.
+
+# From Tim Parenti (2014-07-03):
+# Asia/Sakhalin covers...
+# 65	RU-SAK	Sakhalin Oblast
+# ...with the exception of:
+# 65-11	****	Severo-Kurilsky District (North Kuril Islands)
+
+# The Zone name should be Asia/Yuzhno-Sakhalinsk, but that's too long.
 Zone Asia/Sakhalin	 9:30:48 -	LMT	1905 Aug 23
-			 9:00	-	CJT	1938
+			 9:00	-	JCST	1937 Oct  1
 			 9:00	-	JST	1945 Aug 25
-			11:00	Russia	SAK%sT	1991 Mar 31 2:00s # Sakhalin T.
-			10:00	Russia	SAK%sT	1992 Jan 19 2:00s
-			11:00	Russia	SAK%sT	1997 Mar lastSun 2:00s
-			10:00	Russia	SAK%sT	2011 Mar 27 2:00s
-			11:00	-	SAKT
-#
-# From Oscar van Vlijmen (2003-10-18): [This region consists of]
-# Magadanskaya oblast', Respublika Sakha (Yakutiya).
-# Probably also: Kuril Islands.
+			11:00	Russia	SAK%sT	1991 Mar 31  2:00s # Sakhalin T
+			10:00	Russia	SAK%sT	1992 Jan 19  2:00s
+			11:00	Russia	SAK%sT	1997 Mar lastSun  2:00s
+			10:00	Russia	SAK%sT	2011 Mar 27  2:00s
+			11:00	-	SAKT	2014 Oct 26  2:00s
+			10:00	-	SAKT
+
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2009-11-29):
+# Asia/Magadan covers...
+# 49	RU-MAG	Magadan Oblast
+
+# From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02):
+# Magadan Oblast is moving from UTC+12 to UTC+10 on 2014-10-26; however,
+# several districts of Sakha Republic as well as Severo-Kurilsky District of
+# the Sakhalin Oblast (also known as the North Kuril Islands), represented
+# until now by Asia/Magadan, will instead move to UTC+11.  These regions will
+# need their own zone.
 
-# From Oscar van Vlijmen (2009-11-29):
-# The Sakha districts are: Abyjskij, Allaikhovskij, Verkhhhnekolymskij, Momskij,
-# Nizhnekolymskij, ... Srednekolymskij.
 Zone Asia/Magadan	10:03:12 -	LMT	1924 May  2
 			10:00	-	MAGT	1930 Jun 21 # Magadan Time
-			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
-			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
-			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
-			12:00	-	MAGT
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2014 Oct 26  2:00s
+			10:00	-	MAGT
+
+
+# From Tim Parenti (2014-07-06):
+# Asia/Srednekolymsk covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-01	****	Abyysky District
+# 14-03	****	Allaikhovsky District
+# 14-08	****	Verkhnekolymsky District
+# 14-17	****	Momsky District
+# 14-20	****	Nizhnekolymsky District
+# 14-25	****	Srednekolymsky District
+#
+# ...and parts of (65, RU-SAK) Sakhalin Oblast:
+# 65-11	****	Severo-Kurilsky District (North Kuril Islands)
+
+# From Tim Parenti (2014-07-02):
+# Oymyakonsky District of Sakha Republic (represented by Ust-Nera), along with
+# most of Sakhalin Oblast (represented by Sakhalin) will be moving to UTC+10 on
+# 2014-10-26 to stay aligned with VLAT/SAKT; however, Severo-Kurilsky District
+# of the Sakhalin Oblast (also known as the North Kuril Islands, represented by
+# Severo-Kurilsk) will remain on UTC+11.
+
+# From Tim Parenti (2014-07-06):
+# Assume North Kuril Islands have history like Magadan before 2011-03-27.
+# There is a decent chance this is wrong, in which case a new zone
+# Asia/Severo-Kurilsk would become necessary.
+#
+# Srednekolymsk and Zyryanka are the most populous places amongst these
+# districts, but have very similar populations.  In fact, Wikipedia currently
+# lists them both as having 3528 people, exactly 1668 males and 1860 females
+# each!  (Yikes!)
+# http://en.wikipedia.org/w/?title=Srednekolymsky_District&oldid=603435276
+# http://en.wikipedia.org/w/?title=Verkhnekolymsky_District&oldid=594378493
+# Assume this is a mistake, albeit an amusing one.
+#
+# Looking at censuses, the populations of the two municipalities seem to have
+# fluctuated recently.  Zyryanka was more populous than Srednekolymsk in the
+# 1989 and 2002 censuses, but Srednekolymsk was more populous in the most
+# recent (2010) census, 3525 to 3170.  (See pages 195 and 197 of
+# http://www.gks.ru/free_doc/new_site/perepis2010/croc/Documents/Vol1/pub-01-05.pdf
+# in Russian.)  In addition, Srednekolymsk appears to be a much older
+# settlement and the population of Zyryanka seems to be declining.
+# Go with Srednekolymsk.
+#
+# Since Magadan Oblast moves to UTC+10 on 2014-10-26, we cannot keep using MAGT
+# as the abbreviation.  Use SRET instead.
+
+Zone Asia/Srednekolymsk	10:14:52 -	LMT	1924 May  2
+			10:00	-	MAGT	1930 Jun 21 # Magadan Time
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2014 Oct 26  2:00s
+			11:00	-	SRET	# Srednekolymsk Time
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Ust-Nera covers parts of (14, RU-SA) Sakha (Yakutia) Republic:
+# 14-22	****	Oymyakonsky District
 
 # From Arthur David Olson (2012-05-09):
-# Ojmyakonskij and the Kuril Islands switched from
+# Ojmyakonskij [and the Kuril Islands] switched from
 # Magadan time to Vladivostok time in 2011.
+#
+# From Tim Parenti (2014-07-06), per Alexander Krivenyshev (2014-07-02):
+# It's unlikely that any of the Kuril Islands were involved in such a switch,
+# as the South and Middle Kurils have been on UTC+11 (SAKT) with the rest of
+# Sakhalin Oblast since at least 2011-09, and the North Kurils have been on
+# UTC+12 since at least then, too.
+
 Zone Asia/Ust-Nera	 9:32:54 -	LMT	1919 Dec 15
 			 8:00	-	YAKT	1930 Jun 21 # Yakutsk Time
 			 9:00	Russia	YAKT	1981 Apr  1
-			11:00	Russia	MAG%sT	1991 Mar 31 2:00s
-			10:00	Russia	MAG%sT	1992 Jan 19 2:00s
-			11:00	Russia	MAG%sT	2011 Mar 27 2:00s
-			12:00	-	MAGT	2011 Sep 13 0:00s # Decree 725?
-			11:00	-	VLAT
+			11:00	Russia	MAG%sT	1991 Mar 31  2:00s
+			10:00	Russia	MAG%sT	1992 Jan 19  2:00s
+			11:00	Russia	MAG%sT	2011 Mar 27  2:00s
+			12:00	-	MAGT	2011 Sep 13  0:00s # Decree 725?
+			11:00	-	VLAT	2014 Oct 26  2:00s
+			10:00	-	VLAT
 
-# From Oscar van Vlijmen (2001-08-25): [This region consists of]
-# Kamchatskaya oblast', Koryakskij avtonomnyj okrug.
+
+# From Tim Parenti (2014-07-03), per Oscar van Vlijmen (2001-08-25):
+# Asia/Kamchatka covers...
+# 91	RU-KAM	Kamchatka Krai
 #
-# The Zone name should be Asia/Petropavlovsk-Kamchatski, but that's too long.
+# Note: Effective 2007-07-01, (41) Kamchatka Oblast and (82) Koryak
+# Autonomous Okrug merged to form (91, RU-KAM) Kamchatka Krai.
+
+# The Zone name should be Asia/Petropavlovsk-Kamchatski or perhaps
+# Asia/Petropavlovsk-Kamchatsky, but these are too long.
 Zone Asia/Kamchatka	10:34:36 -	LMT	1922 Nov 10
 			11:00	-	PETT	1930 Jun 21 # P-K Time
-			12:00	Russia	PET%sT	1991 Mar 31 2:00s
-			11:00	Russia	PET%sT	1992 Jan 19 2:00s
-			12:00	Russia	PET%sT	2010 Mar 28 2:00s
-			11:00	Russia	PET%sT	2011 Mar 27 2:00s
+			12:00	Russia	PET%sT	1991 Mar 31  2:00s
+			11:00	Russia	PET%sT	1992 Jan 19  2:00s
+			12:00	Russia	PET%sT	2010 Mar 28  2:00s
+			11:00	Russia	PET%sT	2011 Mar 27  2:00s
 			12:00	-	PETT
-#
-# Chukotskij avtonomnyj okrug
+
+
+# From Tim Parenti (2014-07-03):
+# Asia/Anadyr covers...
+# 87	RU-CHU	Chukotka Autonomous Okrug
+
 Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
 			12:00	-	ANAT	1930 Jun 21 # Anadyr Time
-			13:00	Russia	ANA%sT	1982 Apr  1 0:00s
-			12:00	Russia	ANA%sT	1991 Mar 31 2:00s
-			11:00	Russia	ANA%sT	1992 Jan 19 2:00s
-			12:00	Russia	ANA%sT	2010 Mar 28 2:00s
-			11:00	Russia	ANA%sT	2011 Mar 27 2:00s
+			13:00	Russia	ANA%sT	1982 Apr  1  0:00s
+			12:00	Russia	ANA%sT	1991 Mar 31  2:00s
+			11:00	Russia	ANA%sT	1992 Jan 19  2:00s
+			12:00	Russia	ANA%sT	2010 Mar 28  2:00s
+			11:00	Russia	ANA%sT	2011 Mar 27  2:00s
 			12:00	-	ANAT
 
+
 # San Marino
 # See Europe/Rome.
 
@@ -2488,11 +2841,11 @@ Zone Asia/Anadyr	11:49:56 -	LMT	1924 May  2
 Zone	Europe/Belgrade	1:22:00	-	LMT	1884
 			1:00	-	CET	1941 Apr 18 23:00
 			1:00	C-Eur	CE%sT	1945
-			1:00	-	CET	1945 May 8 2:00s
+			1:00	-	CET	1945 May  8  2:00s
 			1:00	1:00	CEST	1945 Sep 16  2:00s
-# Metod Kozelj reports that the legal date of
+# Metod Koželj reports that the legal date of
 # transition to EU rules was 1982-11-27, for all of Yugoslavia at the time.
-# Shanks & Pottenger don't give as much detail, so go with Kozelj.
+# Shanks & Pottenger don't give as much detail, so go with Koželj.
 			1:00	-	CET	1982 Nov 27
 			1:00	EU	CE%sT
 Link Europe/Belgrade Europe/Ljubljana	# Slovenia
@@ -2568,13 +2921,13 @@ Zone	Africa/Ceuta	-0:21:16 -	LMT	1901
 			 0:00	1:00	WEST	1918 Oct  7 23:00
 			 0:00	-	WET	1924
 			 0:00	Spain	WE%sT	1929
-			 0:00 SpainAfrica WE%sT 1984 Mar 16
+			 0:00 SpainAfrica WE%sT	1984 Mar 16
 			 1:00	-	CET	1986
 			 1:00	EU	CE%sT
 Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
-			-1:00	-	CANT	1946 Sep 30 1:00 # Canaries Time
-			 0:00	-	WET	1980 Apr  6 0:00s
-			 0:00	1:00	WEST	1980 Sep 28 0:00s
+			-1:00	-	CANT	1946 Sep 30  1:00 # Canaries T
+			 0:00	-	WET	1980 Apr  6  0:00s
+			 0:00	1:00	WEST	1980 Sep 28  0:00s
 			 0:00	EU	WE%sT
 # IATA SSIM (1996-09) says the Canaries switch at 2:00u, not 1:00u.
 # Ignore this for now, as the Canaries are part of the EU.
@@ -2583,7 +2936,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 
 # From Ivan Nilsson (2001-04-13), superseding Shanks & Pottenger:
 #
-# The law "Svensk forfattningssamling 1878, no 14" about standard time in 1879:
+# The law "Svensk författningssamling 1878, no 14" about standard time in 1879:
 # From the beginning of 1879 (that is 01-01 00:00) the time for all
 # places in the country is "the mean solar time for the meridian at
 # three degrees, or twelve minutes of time, to the west of the
@@ -2594,7 +2947,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 # national standard time as 01:00:14 ahead of GMT....
 #
 # About the beginning of CET in Sweden. The lawtext ("Svensk
-# forfattningssamling 1899, no 44") states, that "from the beginning
+# författningssamling 1899, no 44") states, that "from the beginning
 # of 1900... ... the same as the mean solar time for the meridian at
 # the distance of one hour of time from the meridian of the English
 # observatory at Greenwich, or at 12 minutes 14 seconds to the west
@@ -2602,7 +2955,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 # 1899-06-16.  In short: At 1900-01-01 00:00:00 the new standard time
 # in Sweden is 01:00:00 ahead of GMT.
 #
-# 1916: The lawtext ("Svensk forfattningssamling 1916, no 124") states
+# 1916: The lawtext ("Svensk författningssamling 1916, no 124") states
 # that "1916-05-15 is considered to begin one hour earlier". It is
 # pretty obvious that at 05-14 23:00 the clocks are set to 05-15 00:00....
 # Further the law says, that "1916-09-30 is considered to end one hour later".
@@ -2612,7 +2965,7 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 # not available on the site (to my knowledge they are only available
 # in Swedish):  (type
 # "sommartid" without the quotes in the field "Fritext" and then click
-# the Sok-button).
+# the Sök-button).
 #
 # (2001-05-13):
 #
@@ -2627,9 +2980,9 @@ Zone	Atlantic/Canary	-1:01:36 -	LMT	1922 Mar # Las Palmas de Gran C.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
-			1:00:14	-	SET	1900 Jan  1	# Swedish Time
+			1:00:14	-	SET	1900 Jan  1 # Swedish Time
 			1:00	-	CET	1916 May 14 23:00
-			1:00	1:00	CEST	1916 Oct  1 01:00
+			1:00	1:00	CEST	1916 Oct  1  1:00
 			1:00	-	CET	1980
 			1:00	EU	CE%sT
 
@@ -2637,7 +2990,7 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 # From Howse:
 # By the end of the 18th century clocks and watches became commonplace
 # and their performance improved enormously.  Communities began to keep
-# mean time in preference to apparent time -- Geneva from 1780 ....
+# mean time in preference to apparent time - Geneva from 1780 ....
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 # From Whitman (who writes "Midnight?"):
 # Rule	Swiss	1940	only	-	Nov	 2	0:00	1:00	S
@@ -2653,7 +3006,7 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 # to be wrong. This is now verified.
 #
 # I have found copies of the original ruling by the Swiss Federal
-# government, in 'Eidgen[o]ssische Gesetzessammlung 1941 and 1942' (Swiss
+# government, in 'Eidgenössische Gesetzessammlung 1941 and 1942' (Swiss
 # federal law collection)...
 #
 # DST began on Monday 5 May 1941, 1:00 am by shifting the clocks to 2:00 am
@@ -2672,7 +3025,7 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 # night as an absolute novelty, because this was the first time that such
 # a thing had happened in Switzerland.
 #
-# I have also checked 1916, because one book source (Gabriel, Traite de
+# I have also checked 1916, because one book source (Gabriel, Traité de
 # l'heure dans le monde) claims that Switzerland had DST in 1916. This is
 # false, no official document could be found. Probably Gabriel got misled
 # by references to Germany, which introduced DST in 1916 for the first time.
@@ -2686,19 +3039,19 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 # One further detail for Switzerland, which is probably out of scope for
 # most users of tzdata: The [Europe/Zurich zone] ...
 # describes all of Switzerland correctly, with the exception of
-# the Cantone Geneve (Geneva, Genf). Between 1848 and 1894 Geneve did not
+# the Canton de Genève (Geneva, Genf). Between 1848 and 1894 Geneva did not
 # follow Bern Mean Time but kept its own local mean time.
 # To represent this, an extra zone would be needed.
 #
 # From Alois Treindl (2013-09-11):
 # The Federal regulations say
 # http://www.admin.ch/opc/de/classified-compilation/20071096/index.html
-# ... the meridian for Bern mean time ... is 7 degrees 26'22.50".
+# ... the meridian for Bern mean time ... is 7 degrees 26' 22.50".
 # Expressed in time, it is 0h29m45.5s.
 
 # From Pierre-Yves Berger (2013-09-11):
-# the "Circulaire du conseil federal" (December 11 1893)
-#  ...
+# the "Circulaire du conseil fédéral" (December 11 1893)
+# http://www.amtsdruckschriften.bar.admin.ch/viewOrigDoc.do?id=10071353
 # clearly states that the [1894-06-01] change should be done at midnight
 # but if no one is present after 11 at night, could be postponed until one
 # hour before the beginning of service.
@@ -2709,14 +3062,14 @@ Zone Europe/Stockholm	1:12:12 -	LMT	1879 Jan  1
 # We can find no reliable source for Shanks's assertion that all of Switzerland
 # except Geneva switched to Bern Mean Time at 00:00 on 1848-09-12.  This book:
 #
-#	Jakob Messerli. Gleichmassig, punktlich, schnell: Zeiteinteilung und
+#	Jakob Messerli. Gleichmässig, pünktlich, schnell. Zeiteinteilung und
 #	Zeitgebrauch in der Schweiz im 19. Jahrhundert. Chronos, Zurich 1995,
 #	ISBN 3-905311-68-2, OCLC 717570797.
 #
 # suggests that the transition was more gradual, and that the Swiss did not
 # agree about civil time during the transition.  The timekeeping it gives the
 # most detail for is postal and telegraph time: here, federal legislation (the
-# "Bundesgesetz uber die Erstellung von elektrischen Telegraphen") passed on
+# "Bundesgesetz über die Erstellung von elektrischen Telegraphen") passed on
 # 1851-11-23, and an official implementation notice was published 1853-07-16
 # (Bundesblatt 1853, Bd. II, S. 859).  On p 72 Messerli writes that in
 # practice since July 1853 Bernese time was used in "all postal and telegraph
@@ -2730,7 +3083,7 @@ Rule	Swiss	1941	1942	-	May	Mon>=1	1:00	1:00	S
 Rule	Swiss	1941	1942	-	Oct	Mon>=1	2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
-			0:29:46	-	BMT	1894 Jun # Bern Mean Time
+			0:29:46	-	BMT	1894 Jun    # Bern Mean Time
 			1:00	Swiss	CE%sT	1981
 			1:00	EU	CE%sT
 
@@ -2738,7 +3091,7 @@ Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
 
 # From Amar Devegowda (2007-01-03):
 # The time zone rules for Istanbul, Turkey have not been changed for years now.
-# ... The latest rules are available at -
+# ... The latest rules are available at:
 # http://www.timeanddate.com/worldclock/timezone.html?n=107
 # From Steffen Thorsen (2007-01-03):
 # I have been able to find press records back to 1996 which all say that
@@ -2763,8 +3116,7 @@ Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
 # (on a non-government server though) describing dates between 2002 and 2006:
 # http://www.alomaliye.com/bkk_2002_3769.htm
 
-# From Gökdeniz Karadağ (2011-03-10):
-#
+# From Gökdeniz Karadağ (2011-03-10):
 # According to the articles linked below, Turkey will change into summer
 # time zone (GMT+3) on March 28, 2011 at 3:00 a.m. instead of March 27.
 # This change is due to a nationwide exam on 27th.
@@ -2777,9 +3129,16 @@ Zone	Europe/Zurich	0:34:08 -	LMT	1853 Jul 16 # See above comment.
 # Turkish Local election....
 # http://www.sabah.com.tr/Ekonomi/2014/02/12/yaz-saatinde-onemli-degisiklik
 # ... so Turkey will move clocks forward one hour on March 31 at 3:00 a.m.
-# From Paul Eggert (2014-02-17):
-# Here is an English-language source:
-# http://www.worldbulletin.net/turkey/129016/turkey-switches-to-daylight-saving-time-march-31
+# From Randal L. Schwartz (2014-04-15):
+# Having landed on a flight from the states to Istanbul (via AMS) on March 31,
+# I can tell you that NOBODY (even the airlines) respected this timezone DST
+# change delay.  Maybe the word just didn't get out in time.
+# From Paul Eggert (2014-06-15):
+# The press reported massive confusion, as election officials obeyed the rule
+# change but cell phones (and airline baggage systems) did not.  See:
+# Kostidis M. Eventful elections in Turkey. Balkan News Agency
+# http://www.balkaneu.com/eventful-elections-turkey/ 2014-03-30.
+# I guess the best we can do is document the official time.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Turkey	1916	only	-	May	 1	0:00	1:00	S
@@ -2846,10 +3205,10 @@ Zone	Europe/Istanbul	1:55:52 -	LMT	1880
 			2:00	Turkey	EE%sT	1978 Oct 15
 			3:00	Turkey	TR%sT	1985 Apr 20 # Turkey Time
 			2:00	Turkey	EE%sT	2007
-			2:00	EU	EE%sT	2011 Mar 27 1:00u
-			2:00	-	EET	2011 Mar 28 1:00u
-			2:00	EU	EE%sT	2014 Mar 30 1:00u
-			2:00	-	EET	2014 Mar 31 1:00u
+			2:00	EU	EE%sT	2011 Mar 27  1:00u
+			2:00	-	EET	2011 Mar 28  1:00u
+			2:00	EU	EE%sT	2014 Mar 30  1:00u
+			2:00	-	EET	2014 Mar 31  1:00u
 			2:00	EU	EE%sT
 Link	Europe/Istanbul	Asia/Istanbul	# Istanbul is in both continents.
 
@@ -2870,7 +3229,7 @@ Link	Europe/Istanbul	Asia/Istanbul	# Istanbul is in both continents.
 # Bill number 8330 of MP from the Party of Regions Oleg Nadoshi got
 # approval from 266 deputies.
 #
-# Ukraine abolishes transter back to the winter time (in Russian)
+# Ukraine abolishes transfer back to the winter time (in Russian)
 # http://news.mail.ru/politics/6861560/
 #
 # The Ukrainians will no longer change the clock (in Russian)
@@ -2931,12 +3290,12 @@ Zone Europe/Kiev	2:02:04 -	LMT	1880
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Sep 20
 			1:00	C-Eur	CE%sT	1943 Nov  6
-			3:00	Russia	MSK/MSD	1990 Jul  1 2:00
-			2:00	1:00	EEST	1991 Sep 29 3:00
+			3:00	Russia	MSK/MSD	1990 Jul  1  2:00
+			2:00	1:00	EEST	1991 Sep 29  3:00
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
 # Ruthenia used CET 1990/1991.
-# "Uzhhorod" is the transliteration of the Ukrainian name, but
+# "Uzhhorod" is the transliteration of the Rusyn/Ukrainian pronunciation, but
 # "Uzhgorod" is more common in English.
 Zone Europe/Uzhgorod	1:29:12 -	LMT	1890 Oct
 			1:00	-	CET	1940
@@ -2944,8 +3303,8 @@ Zone Europe/Uzhgorod	1:29:12 -	LMT	1890 Oct
 			1:00	1:00	CEST	1944 Oct 26
 			1:00	-	CET	1945 Jun 29
 			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1990 Jul  1 2:00
-			1:00	-	CET	1991 Mar 31 3:00
+			3:00	-	MSK	1990 Jul  1  2:00
+			1:00	-	CET	1991 Mar 31  3:00
 			2:00	-	EET	1992
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
@@ -2959,42 +3318,9 @@ Zone Europe/Zaporozhye	2:20:40 -	LMT	1880
 			2:00	-	EET	1930 Jun 21
 			3:00	-	MSK	1941 Aug 25
 			1:00	C-Eur	CE%sT	1943 Oct 25
-			3:00	Russia	MSK/MSD	1991 Mar 31 2:00
+			3:00	Russia	MSK/MSD	1991 Mar 31  2:00
 			2:00	E-Eur	EE%sT	1995
 			2:00	EU	EE%sT
-# Central Crimea used Moscow time 1994/1997.
-Zone Europe/Simferopol	2:16:24 -	LMT	1880
-			2:16	-	SMT	1924 May  2 # Simferopol Mean T
-			2:00	-	EET	1930 Jun 21
-			3:00	-	MSK	1941 Nov
-			1:00	C-Eur	CE%sT	1944 Apr 13
-			3:00	Russia	MSK/MSD	1990
-			3:00	-	MSK	1990 Jul  1 2:00
-			2:00	-	EET	1992
-# From Paul Eggert (2006-03-22):
-# The _Economist_ (1994-05-28, p 45) reports that central Crimea switched
-# from Kiev to Moscow time sometime after the January 1994 elections.
-# Shanks (1999) says "date of change uncertain", but implies that it happened
-# sometime between the 1994 DST switches.  Shanks & Pottenger simply say
-# 1994-09-25 03:00, but that can't be right.  For now, guess it
-# changed in May.
-			2:00	E-Eur	EE%sT	1994 May
-# From IATA SSIM (1994/1997), which also says that Kerch is still like Kiev.
-			3:00	E-Eur	MSK/MSD	1996 Mar 31 3:00s
-			3:00	1:00	MSD	1996 Oct 27 3:00s
-# IATA SSIM (1997-09) says Crimea switched to EET/EEST.
-# Assume it happened in March by not changing the clocks.
-			3:00	Russia	MSK/MSD	1997
-			3:00	-	MSK	1997 Mar lastSun 1:00u
-# From Alexander Krivenyshev (2014-03-17):
-# time change at 2:00 (2am) on March 30, 2014
-# http://vz.ru/news/2014/3/17/677464.html
-# From Paul Eggert (2014-03-30):
-# Simferopol and Sevastopol reportedly changed their central town clocks
-# late the previous day, but this appears to have been ceremonial
-# and the discrepancies are small enough to not worry about.
-			2:00	EU	EE%sT	2014 Mar 30 2:00
-			4:00	-	MSK
 
 # Vatican City
 # See Europe/Rome.
@@ -3018,7 +3344,7 @@ Zone Europe/Simferopol	2:16:24 -	LMT	1880
 # ...
 #
 # ...the European time rules are...standardized since 1981, when
-# most European coun[tr]ies started DST.  Before that year, only
+# most European countries started DST.  Before that year, only
 # a few countries (UK, France, Italy) had DST, each according
 # to own national rules.  In 1981, however, DST started on
 # 'Apr firstSun', and not on 'Mar lastSun' as in the following
@@ -3026,7 +3352,7 @@ Zone Europe/Simferopol	2:16:24 -	LMT	1880
 # But also since 1981 there are some more national exceptions
 # than listed in 'europe': Switzerland, for example, joined DST
 # one year later, Denmark ended DST on 'Oct 1' instead of 'Sep
-# lastSun' in 1981---I don't know how they handle now.
+# lastSun' in 1981 - I don't know how they handle now.
 #
 # Finally, DST ist always from 'Apr 1' to 'Oct 1' in the
 # Soviet Union (as far as I know).
diff --git a/jdk/make/data/tzdata/factory b/jdk/make/data/tzdata/factory
index 813d99a1f1f..0a6041db07e 100644
--- a/jdk/make/data/tzdata/factory
+++ b/jdk/make/data/tzdata/factory
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
diff --git a/jdk/make/data/tzdata/iso3166.tab b/jdk/make/data/tzdata/iso3166.tab
index 28fb64b647e..63eadcbd0c5 100644
--- a/jdk/make/data/tzdata/iso3166.tab
+++ b/jdk/make/data/tzdata/iso3166.tab
@@ -26,21 +26,21 @@
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 #
-# From Paul Eggert (2013-05-27):
+# From Paul Eggert (2014-07-18):
+# This file contains a table of two-letter country codes.  Columns are
+# separated by a single tab.  Lines beginning with '#' are comments.
+# Although all text currently uses ASCII encoding, this is planned to
+# change to UTF-8 soon.  The columns of the table are as follows:
 #
-# This file contains a table with the following columns:
 # 1.  ISO 3166-1 alpha-2 country code, current as of
-#     ISO 3166-1 Newsletter VI-15 (2013-05-10).  See: Updates on ISO 3166
+#     ISO 3166-1 Newsletter VI-16 (2013-07-11).  See: Updates on ISO 3166
 #   http://www.iso.org/iso/home/standards/country_codes/updates_on_iso_3166.htm
 # 2.  The usual English name for the coded region,
 #     chosen so that alphabetic sorting of subsets produces helpful lists.
 #     This is not the same as the English name in the ISO 3166 tables.
 #
-# Columns are separated by a single tab.
 # The table is sorted by country code.
 #
-# Lines beginning with `#' are comments.
-#
 # This table is intended as an aid for users, to help them select time
 # zone data appropriate for their practical needs.  It is not intended
 # to take or endorse any position on legal or territorial claims.
diff --git a/jdk/make/data/tzdata/leapseconds b/jdk/make/data/tzdata/leapseconds
index b423135b942..d38abd6a4bd 100644
--- a/jdk/make/data/tzdata/leapseconds
+++ b/jdk/make/data/tzdata/leapseconds
@@ -21,7 +21,7 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# Allowance for leapseconds added to each timezone file.
+# Allowance for leap seconds added to each time zone file.
 
 # This file is in the public domain.
 
@@ -31,7 +31,7 @@
 # you should be able to pick up leap-seconds.list from a secondary NIST server.
 # For more about leap-seconds.list, please see
 # The NTP Timescale and Leap Seconds
-# .
+# http://www.eecis.udel.edu/~mills/leap.html
 
 # The International Earth Rotation Service periodically uses leap seconds
 # to keep UTC to within 0.9 s of UT1
diff --git a/jdk/make/data/tzdata/northamerica b/jdk/make/data/tzdata/northamerica
index dc0c2e92cff..0dc714aa92d 100644
--- a/jdk/make/data/tzdata/northamerica
+++ b/jdk/make/data/tzdata/northamerica
@@ -21,15 +21,15 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
 # also includes Central America and the Caribbean
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (1999-03-22):
 # A reliable and entertaining source about time zones is
@@ -78,13 +78,13 @@
 #	to push people into bed earlier, and get them up earlier, to make
 #	them healthy, wealthy and wise in spite of themselves.
 #
-#	-- Robertson Davies, The diary of Samuel Marchbanks,
+#	 -- Robertson Davies, The diary of Samuel Marchbanks,
 #	   Clarke, Irwin (1947), XIX, Sunday
 #
 # For more about the first ten years of DST in the United States, see
-# Robert Garland's 
-# Ten years of daylight saving from the Pittsburgh standpoint
-# (Carnegie Library of Pittsburgh, 1927).
+# Robert Garland, Ten years of daylight saving from the Pittsburgh standpoint
+# (Carnegie Library of Pittsburgh, 1927).
+# http://www.clpgh.org/exhibit/dst.html
 #
 # Shanks says that DST was called "War Time" in the US in 1918 and 1919.
 # However, DST was imposed by the Standard Time Act of 1918, which
@@ -103,11 +103,11 @@
 # From Arthur David Olson (2000-09-25):
 # Last night I heard part of a rebroadcast of a 1945 Arch Oboler radio drama.
 # In the introduction, Oboler spoke of "Eastern Peace Time."
-# An AltaVista search turned up
-# :
+# An AltaVista search turned up:
+# http://rowayton.org/rhs/hstaug45.html
 # "When the time is announced over the radio now, it is 'Eastern Peace
 # Time' instead of the old familiar 'Eastern War Time.'  Peace is wonderful."
-#  (August 1945) by way of confirmation.
+# (August 1945) by way of confirmation.
 
 # From Joseph Gallant citing
 # George H. Douglas, _The Early Days of Radio Broadcasting_ (1987):
@@ -205,7 +205,7 @@ Zone	PST8PDT		 -8:00	US	P%sT
 # USA  ALASKA STD    9 H  BEHIND UTC    MOST OF ALASKA     (AKST)
 # USA  ALASKA STD    8 H  BEHIND UTC    APR 3 - OCT 30 (AKDT)
 # USA  ALEUTIAN     10 H  BEHIND UTC    ISLANDS WEST OF 170W
-# USA  - " -         9 H  BEHIND UTC    APR 3 - OCT 30
+# USA    "           9 H  BEHIND UTC    APR 3 - OCT 30
 # USA  HAWAII       10 H  BEHIND UTC
 # USA  BERING       11 H  BEHIND UTC    SAMOA, MIDWAY
 
@@ -258,19 +258,19 @@ Zone	PST8PDT		 -8:00	US	P%sT
 # The following was signed into law on 2005-08-08.
 #
 # H.R. 6, Energy Policy Act of 2005, SEC. 110. DAYLIGHT SAVINGS.
-#   (a) Amendment- Section 3(a) of the Uniform Time Act of 1966 (15
+#   (a) Amendment.--Section 3(a) of the Uniform Time Act of 1966 (15
 #   U.S.C. 260a(a)) is amended--
-#     (1) by striking 'first Sunday of April' and inserting 'second
-#     Sunday of March'; and
-#     (2) by striking 'last Sunday of October' and inserting 'first
+#     (1) by striking "first Sunday of April" and inserting "second
+#     Sunday of March"; and
+#     (2) by striking "last Sunday of October" and inserting "first
 #     Sunday of November'.
-#   (b) Effective Date- Subsection (a) shall take effect 1 year after the
+#   (b) Effective Date.--Subsection (a) shall take effect 1 year after the
 #   date of enactment of this Act or March 1, 2007, whichever is later.
-#   (c) Report to Congress- Not later than 9 months after the effective
+#   (c) Report to Congress.--Not later than 9 months after the effective
 #   date stated in subsection (b), the Secretary shall report to Congress
 #   on the impact of this section on energy consumption in the United
 #   States.
-#   (d) Right to Revert- Congress retains the right to revert the
+#   (d) Right to Revert.--Congress retains the right to revert the
 #   Daylight Saving Time back to the 2005 time schedules once the
 #   Department study is complete.
 
@@ -292,7 +292,7 @@ Zone	PST8PDT		 -8:00	US	P%sT
 
 # From Paul Eggert (2005-08-26):
 # According to today's Huntsville Times
-# 
+# http://www.al.com/news/huntsvilletimes/index.ssf?/base/news/1125047783228320.xml&coll=1
 # a few towns on Alabama's "eastern border with Georgia, such as Phenix City
 # in Russell County, Lanett in Chambers County and some towns in Lee County,
 # set their watches and clocks on Eastern time."  It quotes H.H. "Bubba"
@@ -347,15 +347,15 @@ Rule	Chicago	1955	1966	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Chicago	-5:50:36 -	LMT	1883 Nov 18 12:09:24
 			-6:00	US	C%sT	1920
-			-6:00	Chicago	C%sT	1936 Mar  1 2:00
-			-5:00	-	EST	1936 Nov 15 2:00
+			-6:00	Chicago	C%sT	1936 Mar  1  2:00
+			-5:00	-	EST	1936 Nov 15  2:00
 			-6:00	Chicago	C%sT	1942
 			-6:00	US	C%sT	1946
 			-6:00	Chicago	C%sT	1967
 			-6:00	US	C%sT
 # Oliver County, ND switched from mountain to central time on 1992-10-25.
 Zone America/North_Dakota/Center -6:45:12 - LMT	1883 Nov 18 12:14:48
-			-7:00	US	M%sT	1992 Oct 25 02:00
+			-7:00	US	M%sT	1992 Oct 25  2:00
 			-6:00	US	C%sT
 # Morton County, ND, switched from mountain to central time on
 # 2003-10-26, except for the area around Mandan which was already central time.
@@ -364,29 +364,26 @@ Zone America/North_Dakota/Center -6:45:12 - LMT	1883 Nov 18 12:14:48
 # Jones, Mellette, and Todd Counties in South Dakota;
 # but in practice these other counties were already observing central time.
 # See .
-Zone America/North_Dakota/New_Salem -6:45:39 - LMT 1883 Nov 18 12:14:21
-			-7:00	US	M%sT	2003 Oct 26 02:00
+Zone America/North_Dakota/New_Salem -6:45:39 - LMT	1883 Nov 18 12:14:21
+			-7:00	US	M%sT	2003 Oct 26  2:00
 			-6:00	US	C%sT
 
 # From Josh Findley (2011-01-21):
 # ...it appears that Mercer County, North Dakota, changed from the
 # mountain time zone to the central time zone at the last transition from
 # daylight-saving to standard time (on Nov. 7, 2010):
-# 
 # http://www.gpo.gov/fdsys/pkg/FR-2010-09-29/html/2010-24376.htm
-# 
-# 
 # http://www.bismarcktribune.com/news/local/article_1eb1b588-c758-11df-b472-001cc4c03286.html
-# 
 
 # From Andy Lipscomb (2011-01-24):
 # ...according to the Census Bureau, the largest city is Beulah (although
 # it's commonly referred to as Beulah-Hazen, with Hazen being the next
 # largest city in Mercer County).  Google Maps places Beulah's city hall
-# at 4715'51" north, 10146'40" west, which yields an offset of 6h47'07".
+# at 47 degrees 15' 51" N, 101 degrees 46' 40" W, which yields an offset
+# of 6h47'07".
 
-Zone America/North_Dakota/Beulah -6:47:07 - LMT 1883 Nov 18 12:12:53
-			-7:00	US	M%sT	2010 Nov  7 2:00
+Zone America/North_Dakota/Beulah -6:47:07 - LMT	1883 Nov 18 12:12:53
+			-7:00	US	M%sT	2010 Nov  7  2:00
 			-6:00	US	C%sT
 
 # US mountain time, represented by Denver
@@ -448,15 +445,18 @@ Zone America/Los_Angeles -7:52:58 -	LMT	1883 Nov 18 12:07:02
 # was destroyed in 1805 by a Yakutat-kon war party.)  However, there
 # were nearby inhabitants in some cases and for our purposes perhaps
 # it's best to simply use the official transition.
-#
 
-# From Steve Ferguson (2011-01-31):
-# The author lives in Alaska and many of the references listed are only
-# available to Alaskan residents.
+# From Paul Eggert (2014-07-18):
+# One opinion of the early-1980s turmoil in Alaska over time zones and
+# daylight saving time appeared as graffiti on a Juneau airport wall:
+# "Welcome to Juneau.  Please turn your watch back to the 19th century."
+# See: Turner W. Alaska's four time zones now two. NY Times 1983-11-01.
+# http://www.nytimes.com/1983/11/01/us/alaska-s-four-time-zones-now-two.html
 #
-# 
-# http://www.alaskahistoricalsociety.org/index.cfm?section=discover%20alaska&page=Glimpses%20of%20the%20Past&viewpost=2&ContentId=98
-# 
+# Steve Ferguson (2011-01-31) referred to the following source:
+# Norris F. Keeping time in Alaska: national directives, local response.
+# Alaska History 2001;16(1-2).
+# http://alaskahistoricalsociety.org/discover-alaska/glimpses-of-the-past/keeping-time-in-alaska/
 
 # From Arthur David Olson (2011-02-01):
 # Here's database-relevant material from the 2001 "Alaska History" article:
@@ -482,12 +482,10 @@ Zone America/Los_Angeles -7:52:58 -	LMT	1883 Nov 18 12:07:02
 # From Arthur David Olson (2011-02-09):
 # I just spoke by phone with a staff member at the Metlakatla Indian
 # Community office (using contact information available at
-# 
 # http://www.commerce.state.ak.us/dca/commdb/CIS.cfm?Comm_Boro_name=Metlakatla
-# ).
 # It's shortly after 1:00 here on the east coast of the United States;
 # the staffer said it was shortly after 10:00 there. When I asked whether
-# that meant they were on Pacific time, they said no--they were on their
+# that meant they were on Pacific time, they said no - they were on their
 # own time. I asked about daylight saving; they said it wasn't used. I
 # did not inquire about practices in the past.
 
@@ -501,9 +499,9 @@ Zone America/Juneau	 15:02:19 -	LMT	1867 Oct 18
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1980 Apr 27 2:00
-			 -9:00	US	Y%sT	1980 Oct 26 2:00
-			 -8:00	US	P%sT	1983 Oct 30 2:00
+			 -8:00	US	P%sT	1980 Apr 27  2:00
+			 -9:00	US	Y%sT	1980 Oct 26  2:00
+			 -8:00	US	P%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Sitka	 14:58:47 -	LMT	1867 Oct 18
@@ -511,7 +509,7 @@ Zone America/Sitka	 14:58:47 -	LMT	1867 Oct 18
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1983 Oct 30 2:00
+			 -8:00	US	P%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Metlakatla	 15:13:42 -	LMT	1867 Oct 18
@@ -519,8 +517,8 @@ Zone America/Metlakatla	 15:13:42 -	LMT	1867 Oct 18
 			 -8:00	-	PST	1942
 			 -8:00	US	P%sT	1946
 			 -8:00	-	PST	1969
-			 -8:00	US	P%sT	1983 Oct 30 2:00
-			 -8:00	-	MeST
+			 -8:00	US	P%sT	1983 Oct 30  2:00
+			 -8:00	-	PST
 Zone America/Yakutat	 14:41:05 -	LMT	1867 Oct 18
 			 -9:18:55 -	LMT	1900 Aug 20 12:00
 			 -9:00	-	YST	1942
@@ -535,7 +533,7 @@ Zone America/Anchorage	 14:00:24 -	LMT	1867 Oct 18
 			-10:00	US	CAT/CAPT 1946 # Peace
 			-10:00	-	CAT	1967 Apr
 			-10:00	-	AHST	1969
-			-10:00	US	AH%sT	1983 Oct 30 2:00
+			-10:00	US	AH%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Nome	 12:58:21 -	LMT	1867 Oct 18
@@ -544,7 +542,7 @@ Zone America/Nome	 12:58:21 -	LMT	1867 Oct 18
 			-11:00	US	N%sT	1946
 			-11:00	-	NST	1967 Apr
 			-11:00	-	BST	1969
-			-11:00	US	B%sT	1983 Oct 30 2:00
+			-11:00	US	B%sT	1983 Oct 30  2:00
 			 -9:00	US	Y%sT	1983 Nov 30
 			 -9:00	US	AK%sT
 Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
@@ -553,7 +551,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
 			-11:00	US	N%sT	1946
 			-11:00	-	NST	1967 Apr
 			-11:00	-	BST	1969
-			-11:00	US	B%sT	1983 Oct 30 2:00
+			-11:00	US	B%sT	1983 Oct 30  2:00
 			-10:00	US	AH%sT	1983 Nov 30
 			-10:00	US	HA%sT
 # The following switches don't quite make our 1970 cutoff.
@@ -571,7 +569,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
 #  Minutes of the Unalaska City Council Meeting, January 10, 1967:
 #  "Except for St. Paul and Akutan, Unalaska is the only important
 #  location not on Alaska Standard Time.  The following resolution was
-#  made by William Robinson and seconded by Henry Swanson:  Be it
+#  made by William Robinson and seconded by Henry Swanson: Be it
 #  resolved that the City of Unalaska hereby goes to Alaska Standard
 #  Time as of midnight Friday, January 13, 1967 (1 A.M. Saturday,
 #  January 14, Alaska Standard Time.)  This resolution was passed with
@@ -583,9 +581,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
 # "Hawaiian Time" by Robert C. Schmitt and Doak C. Cox appears on pages 207-225
 # of volume 26 of The Hawaiian Journal of History (1992). As of 2010-12-09,
 # the article is available at
-# 
 # http://evols.library.manoa.hawaii.edu/bitstream/10524/239/2/JL26215.pdf
-# 
 # and indicates that standard time was adopted effective noon, January
 # 13, 1896 (page 218), that in "1933, the Legislature decreed daylight
 # saving for the period between the last Sunday of each April and the
@@ -606,7 +602,7 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
 # year, the standard time of this Territory shall be advanced one
 # hour...This Act shall take effect upon its approval. Approved this 26th
 # day of April, A. D. 1933. LAWRENCE M JUDD, Governor of the Territory of
-# Hawaii." Page 172:  "Act 163...Act 90 of the Session Laws of 1933 is
+# Hawaii." Page 172: "Act 163...Act 90 of the Session Laws of 1933 is
 # hereby repealed...This Act shall take effect upon its approval, upon
 # which date the standard time of this Territory shall be restored to
 # that existing immediately prior to the taking effect of said Act 90.
@@ -616,14 +612,14 @@ Zone America/Adak	 12:13:21 -	LMT	1867 Oct 18
 # Note that 1933-05-21 was a Sunday.
 # We're left to guess the time of day when Act 163 was approved; guess noon.
 
-Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00 #Schmitt&Cox
-			-10:30	-	HST	1933 Apr 30 2:00 #Laws 1933
-			-10:30	1:00	HDT	1933 May 21 12:00 #Laws 1933+12
-			-10:30	-	HST	1942 Feb 09 2:00 #Schmitt&Cox+2
-			-10:30	1:00	HDT	1945 Sep 30 2:00 #Schmitt&Cox+2
-			-10:30	-	HST	1947 Jun  8 2:00 #Schmitt&Cox+2
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
+Zone Pacific/Honolulu	-10:31:26 -	LMT	1896 Jan 13 12:00
+			-10:30	-	HST	1933 Apr 30  2:00
+			-10:30	1:00	HDT	1933 May 21 12:00
+			-10:30	-	HST	1942 Feb  9  2:00
+			-10:30	1:00	HDT	1945 Sep 30  2:00
+			-10:30	-	HST	1947 Jun  8  2:00
 			-10:00	-	HST
-
 Link Pacific/Honolulu Pacific/Johnston
 
 # Now we turn to US areas that have diverged from the consensus since 1970.
@@ -633,9 +629,9 @@ Link Pacific/Honolulu Pacific/Johnston
 # From Paul Eggert (2002-10-20):
 #
 # The information in the rest of this paragraph is derived from the
-# 
-# Daylight Saving Time web page (2002-01-23) maintained by the
-# Arizona State Library, Archives and Public Records.
+# Daylight Saving Time web page
+#  (2002-01-23)
+# maintained by the Arizona State Library, Archives and Public Records.
 # Between 1944-01-01 and 1944-04-01 the State of Arizona used standard
 # time, but by federal law railroads, airlines, bus lines, military
 # personnel, and some engaged in interstate commerce continued to
@@ -649,10 +645,11 @@ Link Pacific/Honolulu Pacific/Johnston
 # Shanks says the 1944 experiment came to an end on 1944-03-17.
 # Go with the Arizona State Library instead.
 
+# Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Phoenix	-7:28:18 -	LMT	1883 Nov 18 11:31:42
-			-7:00	US	M%sT	1944 Jan  1 00:01
-			-7:00	-	MST	1944 Apr  1 00:01
-			-7:00	US	M%sT	1944 Oct  1 00:01
+			-7:00	US	M%sT	1944 Jan  1  0:01
+			-7:00	-	MST	1944 Apr  1  0:01
+			-7:00	US	M%sT	1944 Oct  1  0:01
 			-7:00	-	MST	1967
 			-7:00	US	M%sT	1968 Mar 21
 			-7:00	-	MST
@@ -676,24 +673,22 @@ Zone America/Phoenix	-7:28:18 -	LMT	1883 Nov 18 11:31:42
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Boise	-7:44:49 -	LMT	1883 Nov 18 12:15:11
-			-8:00	US	P%sT	1923 May 13 2:00
+			-8:00	US	P%sT	1923 May 13  2:00
 			-7:00	US	M%sT	1974
-			-7:00	-	MST	1974 Feb  3 2:00
+			-7:00	-	MST	1974 Feb  3  2:00
 			-7:00	US	M%sT
 
 # Indiana
 #
 # For a map of Indiana's time zone regions, see:
-# 
-# What time is it in Indiana?
-#  (2006-03-01)
+# http://en.wikipedia.org/wiki/Time_in_Indiana
 #
 # From Paul Eggert (2007-08-17):
 # Since 1970, most of Indiana has been like America/Indiana/Indianapolis,
 # with the following exceptions:
 #
 # - Gibson, Jasper, Lake, LaPorte, Newton, Porter, Posey, Spencer,
-#   Vandenburgh, and Warrick counties have been like America/Chicago.
+#   Vanderburgh, and Warrick counties have been like America/Chicago.
 #
 # - Dearborn and Ohio counties have been like America/New_York.
 #
@@ -712,22 +707,16 @@ Zone America/Boise	-7:44:49 -	LMT	1883 Nov 18 12:15:11
 # that they would be ambiguous if we left them at the 'America' level.
 # So we reluctantly put them all in a subdirectory 'America/Indiana'.
 
-# From Paul Eggert (2005-08-16):
-# http://www.mccsc.edu/time.html says that Indiana will use DST starting 2006.
-
-# From Nathan Stratton Treadway (2006-03-30):
-# http://www.dot.gov/affairs/dot0406.htm [3705 B]
-# From Deborah Goldsmith (2006-01-18):
-# http://dmses.dot.gov/docimages/pdf95/382329_web.pdf [2.9 MB]
-# From Paul Eggert (2006-01-20):
-# It says "DOT is relocating the time zone boundary in Indiana to move Starke,
+# From Paul Eggert (2014-06-26):
+# https://www.federalregister.gov/articles/2006/01/20/06-563/standard-time-zone-boundary-in-the-state-of-indiana
+# says "DOT is relocating the time zone boundary in Indiana to move Starke,
 # Pulaski, Knox, Daviess, Martin, Pike, Dubois, and Perry Counties from the
 # Eastern Time Zone to the Central Time Zone.... The effective date of
-# this rule is 2:OO a.m. EST Sunday, April 2, 2006, which is the
+# this rule is 2 a.m. EST Sunday, April 2, 2006, which is the
 # changeover date from standard time to Daylight Saving Time."
-# Strictly speaking, this means the affected counties will change their
-# clocks twice that night, but this obviously is in error.  The intent
-# is that 01:59:59 EST be followed by 02:00:00 CDT.
+# Strictly speaking, this meant the affected counties changed their
+# clocks twice that night, but this obviously was in error.  The intent
+# was that 01:59:59 EST be followed by 02:00:00 CDT.
 
 # From Gwillim Law (2007-02-10):
 # The Associated Press has been reporting that Pulaski County, Indiana is
@@ -739,13 +728,13 @@ Rule Indianapolis 1941	only	-	Jun	22	2:00	1:00	D
 Rule Indianapolis 1941	1954	-	Sep	lastSun	2:00	0	S
 Rule Indianapolis 1946	1954	-	Apr	lastSun	2:00	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Indiana/Indianapolis -5:44:38 - LMT 1883 Nov 18 12:15:22
+Zone America/Indiana/Indianapolis -5:44:38 - LMT	1883 Nov 18 12:15:22
 			-6:00	US	C%sT	1920
 			-6:00 Indianapolis C%sT	1942
 			-6:00	US	C%sT	1946
-			-6:00 Indianapolis C%sT	1955 Apr 24 2:00
-			-5:00	-	EST	1957 Sep 29 2:00
-			-6:00	-	CST	1958 Apr 27 2:00
+			-6:00 Indianapolis C%sT	1955 Apr 24  2:00
+			-5:00	-	EST	1957 Sep 29  2:00
+			-6:00	-	CST	1958 Apr 27  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
 			-5:00	-	EST	2006
@@ -761,10 +750,10 @@ Rule	Marengo	1954	1960	-	Sep	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Marengo -5:45:23 -	LMT	1883 Nov 18 12:14:37
 			-6:00	US	C%sT	1951
-			-6:00	Marengo	C%sT	1961 Apr 30 2:00
+			-6:00	Marengo	C%sT	1961 Apr 30  2:00
 			-5:00	-	EST	1969
-			-5:00	US	E%sT	1974 Jan  6 2:00
-			-6:00	1:00	CDT	1974 Oct 27 2:00
+			-5:00	US	E%sT	1974 Jan  6  2:00
+			-6:00	1:00	CDT	1974 Oct 27  2:00
 			-5:00	US	E%sT	1976
 			-5:00	-	EST	2006
 			-5:00	US	E%sT
@@ -785,11 +774,11 @@ Rule Vincennes	1962	1963	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Vincennes -5:50:07 - LMT	1883 Nov 18 12:09:53
 			-6:00	US	C%sT	1946
-			-6:00 Vincennes	C%sT	1964 Apr 26 2:00
+			-6:00 Vincennes	C%sT	1964 Apr 26  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Nov  4 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Nov  4  2:00
 			-5:00	US	E%sT
 #
 # Perry County, Indiana, switched from eastern to central time in April 2006.
@@ -806,10 +795,10 @@ Rule Perry	1962	1963	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Tell_City -5:47:03 - LMT	1883 Nov 18 12:12:57
 			-6:00	US	C%sT	1946
-			-6:00 Perry	C%sT	1964 Apr 26 2:00
+			-6:00 Perry	C%sT	1964 Apr 26  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
 			-6:00	US	C%sT
 #
 # Pike County, Indiana moved from central to eastern time in 1977,
@@ -822,11 +811,11 @@ Rule	Pike	1961	1964	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Petersburg -5:49:07 - LMT	1883 Nov 18 12:10:53
 			-6:00	US	C%sT	1955
-			-6:00	Pike	C%sT	1965 Apr 25 2:00
-			-5:00	-	EST	1966 Oct 30 2:00
-			-6:00	US	C%sT	1977 Oct 30 2:00
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Nov  4 2:00
+			-6:00	Pike	C%sT	1965 Apr 25  2:00
+			-5:00	-	EST	1966 Oct 30  2:00
+			-6:00	US	C%sT	1977 Oct 30  2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Nov  4  2:00
 			-5:00	US	E%sT
 #
 # Starke County, Indiana moved from central to eastern time in 1991,
@@ -844,10 +833,10 @@ Rule	Starke	1959	1961	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Knox -5:46:30 -	LMT	1883 Nov 18 12:13:30
 			-6:00	US	C%sT	1947
-			-6:00	Starke	C%sT	1962 Apr 29 2:00
-			-5:00	-	EST	1963 Oct 27 2:00
-			-6:00	US	C%sT	1991 Oct 27 2:00
-			-5:00	-	EST	2006 Apr  2 2:00
+			-6:00	Starke	C%sT	1962 Apr 29  2:00
+			-5:00	-	EST	1963 Oct 27  2:00
+			-6:00	US	C%sT	1991 Oct 27  2:00
+			-5:00	-	EST	2006 Apr  2  2:00
 			-6:00	US	C%sT
 #
 # Pulaski County, Indiana, switched from eastern to central time in
@@ -860,17 +849,17 @@ Rule	Pulaski	1957	1960	-	Sep	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Winamac -5:46:25 - LMT	1883 Nov 18 12:13:35
 			-6:00	US	C%sT	1946
-			-6:00	Pulaski	C%sT	1961 Apr 30 2:00
+			-6:00	Pulaski	C%sT	1961 Apr 30  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1971
-			-5:00	-	EST	2006 Apr  2 2:00
-			-6:00	US	C%sT	2007 Mar 11 2:00
+			-5:00	-	EST	2006 Apr  2  2:00
+			-6:00	US	C%sT	2007 Mar 11  2:00
 			-5:00	US	E%sT
 #
 # Switzerland County, Indiana, did not observe DST from 1973 through 2005.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Indiana/Vevay -5:40:16 -	LMT	1883 Nov 18 12:19:44
-			-6:00	US	C%sT	1954 Apr 25 2:00
+			-6:00	US	C%sT	1954 Apr 25  2:00
 			-5:00	-	EST	1969
 			-5:00	US	E%sT	1973
 			-5:00	-	EST	2006
@@ -891,18 +880,17 @@ Zone America/Kentucky/Louisville -5:43:02 -	LMT	1883 Nov 18 12:16:58
 			-6:00	US	C%sT	1921
 			-6:00 Louisville C%sT	1942
 			-6:00	US	C%sT	1946
-			-6:00 Louisville C%sT	1961 Jul 23 2:00
+			-6:00 Louisville C%sT	1961 Jul 23  2:00
 			-5:00	-	EST	1968
-			-5:00	US	E%sT	1974 Jan  6 2:00
-			-6:00	1:00	CDT	1974 Oct 27 2:00
+			-5:00	US	E%sT	1974 Jan  6  2:00
+			-6:00	1:00	CDT	1974 Oct 27  2:00
 			-5:00	US	E%sT
 #
 # Wayne County, Kentucky
 #
-# From
-# 
-# Lake Cumberland LIFE
-#  (1999-01-29) via WKYM-101.7:
+# From Lake Cumberland LIFE
+# http://www.lake-cumberland.com/life/archive/news990129time.shtml
+# (1999-01-29) via WKYM-101.7:
 # Clinton County has joined Wayne County in asking the DoT to change from
 # the Central to the Eastern time zone....  The Wayne County government made
 # the same request in December.  And while Russell County officials have not
@@ -919,9 +907,8 @@ Zone America/Kentucky/Louisville -5:43:02 -	LMT	1883 Nov 18 12:16:58
 #
 # From Paul Eggert (2001-07-16):
 # The final rule was published in the
-# 
-# Federal Register 65, 160 (2000-08-17), page 50154-50158.
-# 
+# Federal Register 65, 160 (2000-08-17), pp 50154-50158.
+# http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=2000_register&docid=fr17au00-22
 #
 Zone America/Kentucky/Monticello -5:39:24 - LMT	1883 Nov 18 12:20:36
 			-6:00	US	C%sT	1946
@@ -946,9 +933,8 @@ Zone America/Kentucky/Monticello -5:39:24 - LMT	1883 Nov 18 12:20:36
 # See America/North_Dakota/Center for the Oliver County, ND change.
 # West Wendover, NV officially switched from Pacific to mountain time on
 # 1999-10-31.  See the
-# 
-# Federal Register 64, 203 (1999-10-21), page 56705-56707.
-# 
+# Federal Register 64, 203 (1999-10-21), pp 56705-56707.
+# http://frwebgate.access.gpo.gov/cgi-bin/getdoc.cgi?dbname=1999_register&docid=fr21oc99-15
 # However, the Federal Register says that West Wendover already operated
 # on mountain time, and the rule merely made this official;
 # hence a separate tz entry is not needed.
@@ -986,12 +972,12 @@ Rule	Detroit	1967	only	-	Jun	14	2:00	1:00	D
 Rule	Detroit	1967	only	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Detroit	-5:32:11 -	LMT	1905
-			-6:00	-	CST	1915 May 15 2:00
+			-6:00	-	CST	1915 May 15  2:00
 			-5:00	-	EST	1942
 			-5:00	US	E%sT	1946
 			-5:00	Detroit	E%sT	1973
 			-5:00	US	E%sT	1975
-			-5:00	-	EST	1975 Apr 27 2:00
+			-5:00	-	EST	1975 Apr 27  2:00
 			-5:00	US	E%sT
 #
 # Dickinson, Gogebic, Iron, and Menominee Counties, Michigan,
@@ -1004,8 +990,8 @@ Rule Menominee	1966	only	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 			-6:00	US	C%sT	1946
-			-6:00 Menominee	C%sT	1969 Apr 27 2:00
-			-5:00	-	EST	1973 Apr 29 2:00
+			-6:00 Menominee	C%sT	1969 Apr 27  2:00
+			-5:00	-	EST	1973 Apr 29  2:00
 			-6:00	US	C%sT
 
 # Navassa
@@ -1042,9 +1028,9 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 #	Whitman Publishing Co, 2 Niagara Av, Ealing, London (undated),
 #	which I found in the UCLA library.
 #
-#	
 #	William Willett, The Waste of Daylight, 19th edition
-#	 (1914-03)
+#	
+#	[PDF] (1914-03)
 #
 #	Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
 #	.
@@ -1053,11 +1039,11 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 
 # Canada
 
-# From Alain LaBont (1994-11-14):
+# From Alain LaBonté (1994-11-14):
 # I post here the time zone abbreviations standardized in Canada
 # for both English and French in the CAN/CSA-Z234.4-89 standard....
 #
-#	UTC	Standard time	Daylight savings time
+#	UTC	Standard time	Daylight saving time
 #	offset	French	English	French	English
 #	-2:30	-	-	HAT	NDT
 #	-3	-	-	HAA	ADT
@@ -1070,7 +1056,7 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 #	-9	HNY	YST	-	-
 #
 #	HN: Heure Normale	ST: Standard Time
-#	HA: Heure Avance	DT: Daylight saving Time
+#	HA: Heure Avancée	DT: Daylight saving Time
 #
 #	A: de l'Atlantique	Atlantic
 #	C: du Centre		Central
@@ -1085,7 +1071,7 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 # From Paul Eggert (1994-11-22):
 # Alas, this sort of thing must be handled by localization software.
 
-# Unless otherwise specified, the data for Canada are all from Shanks
+# Unless otherwise specified, the data entries for Canada are all from Shanks
 # & Pottenger.
 
 # From Chris Walton (2006-04-01, 2006-04-25, 2006-06-26, 2007-01-31,
@@ -1134,15 +1120,15 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 
 # From Paul Eggert (2006-04-25):
 # H. David Matthews and Mary Vincent's map
-# 
 # "It's about TIME", _Canadian Geographic_ (September-October 1998)
-#  contains detailed boundaries for regions observing nonstandard
+# http://www.canadiangeographic.ca/Magazine/SO98/geomap.asp
+# contains detailed boundaries for regions observing nonstandard
 # time and daylight saving time arrangements in Canada circa 1998.
 #
-# INMS, the Institute for National Measurement Standards in Ottawa, has 
+# INMS, the Institute for National Measurement Standards in Ottawa, has
 # information about standard and daylight saving time zones in Canada.
-#  (updated periodically).
+# http://inms-ienm.nrc-cnrc.gc.ca/en/time_services/daylight_saving_e.php
+# (updated periodically).
 # Its unofficial information is often taken from Matthews and Vincent.
 
 # From Paul Eggert (2006-06-27):
@@ -1151,9 +1137,7 @@ Zone America/Menominee	-5:50:27 -	LMT	1885 Sep 18 12:00
 
 # From Chris Walton (2011-12-01)
 # In the first of Tammy Hardwick's articles
-# 
 # http://www.ilovecreston.com/?p=articles&t=spec&ar=260
-# 
 # she quotes the Friday November 1/1918 edition of the Creston Review.
 # The quote includes these two statements:
 # 'Sunday the CPR went back to the old system of time...'
@@ -1221,9 +1205,7 @@ Rule	StJohns	1960	1986	-	Oct	lastSun	2:00	0	S
 # Time to Standard Time and from Standard Time to Daylight Savings Time
 # now occurs at 2:00AM.
 # ...
-# 
 # http://www.assembly.nl.ca/legislation/sr/annualstatutes/2011/1106.chp.htm
-# 
 # ...
 # MICHAEL PELLEY  |  Manager of Enterprise Architecture - Solution Delivery
 # Office of the Chief Information Officer
@@ -1259,7 +1241,7 @@ Zone America/Goose_Bay	-4:01:40 -	LMT	1884 # Happy Valley-Goose Bay
 			-3:30	-	NST	1936
 			-3:30	StJohns	N%sT	1942 May 11
 			-3:30	Canada	N%sT	1946
-			-3:30	StJohns	N%sT	1966 Mar 15 2:00
+			-3:30	StJohns	N%sT	1966 Mar 15  2:00
 			-4:00	StJohns	A%sT	2011 Nov
 			-4:00	Canada	A%sT
 
@@ -1320,7 +1302,7 @@ Rule	Halifax	1962	1973	-	Oct	lastSun	2:00	0	S
 Zone America/Halifax	-4:14:24 -	LMT	1902 Jun 15
 			-4:00	Halifax	A%sT	1918
 			-4:00	Canada	A%sT	1919
-			-4:00	Halifax	A%sT	1942 Feb  9 2:00s
+			-4:00	Halifax	A%sT	1942 Feb  9  2:00s
 			-4:00	Canada	A%sT	1946
 			-4:00	Halifax	A%sT	1974
 			-4:00	Canada	A%sT
@@ -1379,7 +1361,7 @@ Zone America/Moncton	-4:19:08 -	LMT	1883 Dec  9
 # meridian is supposed to observe AST, but residents as far east as
 # Natashquan use EST/EDT, and residents east of Natashquan use AST.
 # The Quebec department of justice writes in
-# "The situation in Minganie and Basse-Cote-Nord"
+# "The situation in Minganie and Basse-Côte-Nord"
 # http://www.justice.gouv.qc.ca/english/publications/generale/temps-minganie-a.htm
 # that the coastal strip from just east of Natashquan to Blanc-Sablon
 # observes Atlantic standard time all year round.
@@ -1387,7 +1369,6 @@ Zone America/Moncton	-4:19:08 -	LMT	1883 Dec  9
 # says this common practice was codified into law as of 2007.
 # For lack of better info, guess this practice began around 1970, contra to
 # Shanks & Pottenger who have this region observing AST/ADT.
-# for post-1970 data America/Puerto_Rico.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Mont	1917	only	-	Mar	25	2:00	1:00	D
@@ -1401,18 +1382,10 @@ Rule	Mont	1922	only	-	Apr	30	2:00	1:00	D
 Rule	Mont	1924	only	-	May	17	2:00	1:00	D
 Rule	Mont	1924	1926	-	Sep	lastSun	2:30	0	S
 Rule	Mont	1925	1926	-	May	Sun>=1	2:00	1:00	D
-# The 1927-to-1937 rules can be expressed more simply as
-# Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
-# Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
-# The rules below avoid use of 24:00
-# (which pre-1998 versions of zic cannot handle).
-Rule	Mont	1927	only	-	May	1	0:00	1:00	D
-Rule	Mont	1927	1932	-	Sep	lastSun	0:00	0	S
-Rule	Mont	1928	1931	-	Apr	lastSun	0:00	1:00	D
-Rule	Mont	1932	only	-	May	1	0:00	1:00	D
-Rule	Mont	1933	1940	-	Apr	lastSun	0:00	1:00	D
-Rule	Mont	1933	only	-	Oct	1	0:00	0	S
-Rule	Mont	1934	1939	-	Sep	lastSun	0:00	0	S
+Rule	Mont	1927	1937	-	Apr	lastSat	24:00	1:00	D
+Rule	Mont	1927	1937	-	Sep	lastSat	24:00	0	S
+Rule	Mont	1938	1940	-	Apr	lastSun	0:00	1:00	D
+Rule	Mont	1938	1939	-	Sep	lastSun	0:00	0	S
 Rule	Mont	1946	1973	-	Apr	lastSun	2:00	1:00	D
 Rule	Mont	1945	1948	-	Sep	lastSun	2:00	0	S
 Rule	Mont	1949	1950	-	Oct	lastSun	2:00	0	S
@@ -1426,7 +1399,7 @@ Zone America/Blanc-Sablon -3:48:28 -	LMT	1884
 Zone America/Montreal	-4:54:16 -	LMT	1884
 			-5:00	Mont	E%sT	1918
 			-5:00	Canada	E%sT	1919
-			-5:00	Mont	E%sT	1942 Feb  9 2:00s
+			-5:00	Mont	E%sT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT	1946
 			-5:00	Mont	E%sT	1974
 			-5:00	Canada	E%sT
@@ -1448,7 +1421,7 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
 # have already done so.  In Orillia DST was to run until Saturday,
 # 1912-08-31 (no time mentioned), but it was met with considerable
 # hostility from certain segments of the public, and was revoked after
-# only two weeks -- I copied it as Saturday, 1912-07-07, 22:00, but
+# only two weeks - I copied it as Saturday, 1912-07-07, 22:00, but
 # presumably that should be -07-06.  (1912-06-19, -07-12; also letters
 # earlier in June).
 #
@@ -1458,10 +1431,8 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
 # Mark Brader writes that an article in the 1997-10-14 Toronto Star
 # says that Atikokan, Ontario currently does not observe DST,
 # but will vote on 11-10 whether to use EST/EDT.
-# He also writes that the
-# 
-# Ontario Time Act (1990, Chapter T.9)
-# 
+# He also writes that the Ontario Time Act (1990, Chapter T.9)
+# http://www.gov.on.ca/MBS/english/publications/statregs/conttext.html
 # says that Ontario east of 90W uses EST/EDT, and west of 90W uses CST/CDT.
 # Officially Atikokan is therefore on CST/CDT, and most likely this report
 # concerns a non-official time observed as a matter of local practice.
@@ -1540,9 +1511,7 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
 # The Journal of The Royal Astronomical Society of Canada,
 # volume 26, number 2 (February 1932) and, as of 2010-07-17,
 # was available at
-# 
 # http://adsabs.harvard.edu/full/1932JRASC..26...49S
-# 
 #
 # It includes the text below (starting on page 57):
 #
@@ -1553,26 +1522,26 @@ Zone America/Montreal	-4:54:16 -	LMT	1884
 # ing in 1930. The information for the province of Quebec is definite,
 # for the other provinces only approximate:
 #
-# 	Province	Daylight saving time used
+#	Province	Daylight saving time used
 # Prince Edward Island	Not used.
 # Nova Scotia		In Halifax only.
 # New Brunswick		In St. John only.
 # Quebec		In the following places:
-# 			Montreal	Lachine
-# 			Quebec		Mont-Royal
-# 			Levis		Iberville
-# 			St. Lambert	Cap de la Madeleine
-# 			Verdun		Loretteville
-# 			Westmount	Richmond
-# 			Outremont	St. Jerome
-# 			Longueuil	Greenfield Park
-# 			Arvida		Waterloo
-# 			Chambly-Canton	Beaulieu
-# 			Melbourne	La Tuque
-# 			St. Theophile	Buckingham
+#			Montreal	Lachine
+#			Quebec		Mont-Royal
+#			Lévis		Iberville
+#			St. Lambert	Cap de la Madelèine
+#			Verdun		Loretteville
+#			Westmount	Richmond
+#			Outremont	St. Jérôme
+#			Longueuil	Greenfield Park
+#			Arvida		Waterloo
+#			Chambly-Canton	Beaulieu
+#			Melbourne	La Tuque
+#			St. Théophile	Buckingham
 # Ontario		Used generally in the cities and towns along
-# 			the southerly part of the province. Not
-# 			used in the northwesterlhy part.
+#			the southerly part of the province. Not
+#			used in the northwesterly part.
 # Manitoba		Not used.
 # Saskatchewan		In Regina only.
 # Alberta		Not used.
@@ -1641,7 +1610,7 @@ Rule	Toronto	1957	1973	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Toronto	-5:17:32 -	LMT	1895
 			-5:00	Canada	E%sT	1919
-			-5:00	Toronto	E%sT	1942 Feb  9 2:00s
+			-5:00	Toronto	E%sT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT	1946
 			-5:00	Toronto	E%sT	1974
 			-5:00	Canada	E%sT
@@ -1654,16 +1623,16 @@ Zone America/Thunder_Bay -5:57:00 -	LMT	1895
 			-5:00	Canada	E%sT
 Zone America/Nipigon	-5:53:04 -	LMT	1895
 			-5:00	Canada	E%sT	1940 Sep 29
-			-5:00	1:00	EDT	1942 Feb  9 2:00s
+			-5:00	1:00	EDT	1942 Feb  9  2:00s
 			-5:00	Canada	E%sT
 Zone America/Rainy_River -6:18:16 -	LMT	1895
 			-6:00	Canada	C%sT	1940 Sep 29
-			-6:00	1:00	CDT	1942 Feb  9 2:00s
+			-6:00	1:00	CDT	1942 Feb  9  2:00s
 			-6:00	Canada	C%sT
 Zone America/Atikokan	-6:06:28 -	LMT	1895
 			-6:00	Canada	C%sT	1940 Sep 29
-			-6:00	1:00	CDT	1942 Feb  9 2:00s
-			-6:00	Canada	C%sT	1945 Sep 30 2:00
+			-6:00	1:00	CDT	1942 Feb  9  2:00s
+			-6:00	Canada	C%sT	1945 Sep 30  2:00
 			-5:00	-	EST
 
 
@@ -1676,7 +1645,7 @@ Zone America/Atikokan	-6:06:28 -	LMT	1895
 # the first Sunday of April of each year and two o'clock Central
 # Standard Time in the morning of the last Sunday of October next
 # following, one hour in advance of Central Standard Time."...
-# I believe that the English legislation [of the old time act] had =
+# I believe that the English legislation [of the old time act] had
 # been assented to (March 22, 1967)....
 # Also, as far as I can tell, there was no order-in-council varying
 # the time of Daylight Saving Time for 2005 and so the provisions of
@@ -1799,12 +1768,12 @@ Rule	Swift	1959	only	-	Oct	lastSun	2:00	0	S
 Rule	Swift	1960	1961	-	Sep	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Regina	-6:58:36 -	LMT	1905 Sep
-			-7:00	Regina	M%sT	1960 Apr lastSun 2:00
+			-7:00	Regina	M%sT	1960 Apr lastSun  2:00
 			-6:00	-	CST
 Zone America/Swift_Current -7:11:20 -	LMT	1905 Sep
-			-7:00	Canada	M%sT	1946 Apr lastSun 2:00
+			-7:00	Canada	M%sT	1946 Apr lastSun  2:00
 			-7:00	Regina	M%sT	1950
-			-7:00	Swift	M%sT	1972 Apr lastSun 2:00
+			-7:00	Swift	M%sT	1972 Apr lastSun  2:00
 			-6:00	-	CST
 
 
@@ -1854,9 +1823,7 @@ Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
 # Earlier this year I stumbled across a detailed article about the time
 # keeping history of Creston; it was written by Tammy Hardwick who is the
 # manager of the Creston & District Museum. The article was written in May 2009.
-# 
 # http://www.ilovecreston.com/?p=articles&t=spec&ar=260
-# 
 # According to the article, Creston has not changed its clocks since June 1918.
 # i.e. Creston has been stuck on UTC-7 for 93 years.
 # Dawson Creek, on the other hand, changed its clocks as recently as April 1972.
@@ -1864,18 +1831,16 @@ Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
 # Unfortunately the exact date for the time change in June 1918 remains
 # unknown and will be difficult to ascertain.  I e-mailed Tammy a few months
 # ago to ask if Sunday June 2 was a reasonable guess.  She said it was just
-# as plausible as any other date (in June).  She also said that after writing the
-# article she had discovered another time change in 1916; this is the subject
-# of another article which she wrote in October 2010.
-# 
+# as plausible as any other date (in June).  She also said that after writing
+# the article she had discovered another time change in 1916; this is the
+# subject of another article which she wrote in October 2010.
 # http://www.creston.museum.bc.ca/index.php?module=comments&uop=view_comment&cm+id=56
-# 
 
 # Here is a summary of the three clock change events in Creston's history:
 # 1. 1884 or 1885: adoption of Mountain Standard Time (GMT-7)
 # Exact date unknown
 # 2. Oct 1916: switch to Pacific Standard Time (GMT-8)
-# Exact date in October unknown;  Sunday October 1 is a reasonable guess.
+# Exact date in October unknown; Sunday October 1 is a reasonable guess.
 # 3. June 1918: switch to Pacific Daylight Time (GMT-7)
 # Exact date in June unknown; Sunday June 2 is a reasonable guess.
 # note#1:
@@ -1888,9 +1853,7 @@ Zone America/Edmonton	-7:33:52 -	LMT	1906 Sep
 # There is no guarantee that Creston will remain on Mountain Standard Time
 # (UTC-7) forever.
 # The subject was debated at least once this year by the town Council.
-# 
 # http://www.bclocalnews.com/kootenay_rockies/crestonvalleyadvance/news/116760809.html
-# 
 
 # During a period WWII, summer time (Daylight saying) was mandatory in Canada.
 # In Creston, that was handled by shifting the area to PST (-8:00) then applying
@@ -1917,7 +1880,7 @@ Zone America/Vancouver	-8:12:28 -	LMT	1884
 			-8:00	Canada	P%sT
 Zone America/Dawson_Creek -8:00:56 -	LMT	1884
 			-8:00	Canada	P%sT	1947
-			-8:00	Vanc	P%sT	1972 Aug 30 2:00
+			-8:00	Vanc	P%sT	1972 Aug 30  2:00
 			-7:00	-	MST
 Zone America/Creston	-7:46:04 -	LMT	1884
 			-7:00	-	MST	1916 Oct 1
@@ -1944,18 +1907,17 @@ Zone America/Creston	-7:46:04 -	LMT	1884
 
 # From Rives McDow (1999-09-04):
 # Nunavut ... moved ... to incorporate the whole territory into one time zone.
-# 
 # Nunavut moves to single time zone Oct. 31
-# 
+# http://www.nunatsiaq.com/nunavut/nvt90903_13.html
 #
 # From Antoine Leca (1999-09-06):
 # We then need to create a new timezone for the Kitikmeot region of Nunavut
 # to differentiate it from the Yellowknife region.
 
 # From Paul Eggert (1999-09-20):
-# 
 # Basic Facts: The New Territory
-#  (1999) reports that Pangnirtung operates on eastern time,
+# http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html
+# (1999) reports that Pangnirtung operates on eastern time,
 # and that Coral Harbour does not observe DST.  We don't know when
 # Pangnirtung switched to eastern time; we'll guess 1995.
 
@@ -1983,8 +1945,8 @@ Zone America/Creston	-7:46:04 -	LMT	1884
 # the current state of affairs.
 
 # From Michaela Rodrigue, writing in the
-# 
-# Nunatsiaq News (1999-11-19):
+# Nunatsiaq News (1999-11-19):
+# http://www.nunatsiaq.com/archives/nunavut991130/nvt91119_17.html
 # Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones,
 # central - or Nunavut time - for government offices, and eastern time
 # for municipal offices and schools....  Igloolik [was similar but then]
@@ -2002,10 +1964,8 @@ Zone America/Creston	-7:46:04 -	LMT	1884
 # Central Time and Southampton Island [in the Central zone] is not
 # required to use daylight savings.
 
-# From
-# 
-# Nunavut now has two time zones
-#  (2000-11-10):
+# From 
+# Nunavut now has two time zones (2000-11-10):
 # The Nunavut government would allow its employees in Kugluktuk and
 # Cambridge Bay to operate on central time year-round, putting them
 # one hour behind the rest of Nunavut for six months during the winter.
@@ -2096,9 +2056,7 @@ Zone America/Creston	-7:46:04 -	LMT	1884
 # used to be the mayor of Resolute Bay and he apparently owns half the
 # businesses including "South Camp Inn." This website has some info on
 # Aziz:
-# 
 # http://www.uphere.ca/node/493
-# 
 #
 # I sent Aziz an e-mail asking when Resolute Bay had stopped using
 # Eastern Standard Time.
@@ -2136,47 +2094,47 @@ Rule	NT_YK	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 # aka Panniqtuuq
 Zone America/Pangnirtung 0	-	zzz	1921 # trading post est.
-			-4:00	NT_YK	A%sT	1995 Apr Sun>=1 2:00
-			-5:00	Canada	E%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
+			-4:00	NT_YK	A%sT	1995 Apr Sun>=1  2:00
+			-5:00	Canada	E%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # formerly Frobisher Bay
 Zone America/Iqaluit	0	-	zzz	1942 Aug # Frobisher Bay est.
-			-5:00	NT_YK	E%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
+			-5:00	NT_YK	E%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
 			-5:00	Canada	E%sT
 # aka Qausuittuq
 Zone America/Resolute	0	-	zzz	1947 Aug 31 # Resolute founded
-			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2001 Apr  1 3:00
-			-6:00	Canada	C%sT	2006 Oct 29 2:00
-			-5:00	-	EST	2007 Mar 11 3:00
+			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2001 Apr  1  3:00
+			-6:00	Canada	C%sT	2006 Oct 29  2:00
+			-5:00	-	EST	2007 Mar 11  3:00
 			-6:00	Canada	C%sT
 # aka Kangiqiniq
 Zone America/Rankin_Inlet 0	-	zzz	1957 # Rankin Inlet founded
-			-6:00	NT_YK	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2001 Apr  1 3:00
+			-6:00	NT_YK	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2001 Apr  1  3:00
 			-6:00	Canada	C%sT
 # aka Iqaluktuuttiaq
 Zone America/Cambridge_Bay 0	-	zzz	1920 # trading post est.?
-			-7:00	NT_YK	M%sT	1999 Oct 31 2:00
-			-6:00	Canada	C%sT	2000 Oct 29 2:00
-			-5:00	-	EST	2000 Nov  5 0:00
-			-6:00	-	CST	2001 Apr  1 3:00
+			-7:00	NT_YK	M%sT	1999 Oct 31  2:00
+			-6:00	Canada	C%sT	2000 Oct 29  2:00
+			-5:00	-	EST	2000 Nov  5  0:00
+			-6:00	-	CST	2001 Apr  1  3:00
 			-7:00	Canada	M%sT
 Zone America/Yellowknife 0	-	zzz	1935 # Yellowknife founded?
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
 Zone America/Inuvik	0	-	zzz	1953 # Inuvik founded
-			-8:00	NT_YK	P%sT	1979 Apr lastSun 2:00
+			-8:00	NT_YK	P%sT	1979 Apr lastSun  2:00
 			-7:00	NT_YK	M%sT	1980
 			-7:00	Canada	M%sT
 Zone America/Whitehorse	-9:00:12 -	LMT	1900 Aug 20
-			-9:00	NT_YK	Y%sT	1966 Jul 1 2:00
+			-9:00	NT_YK	Y%sT	1966 Jul  1  2:00
 			-8:00	NT_YK	P%sT	1980
 			-8:00	Canada	P%sT
 Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
-			-9:00	NT_YK	Y%sT	1973 Oct 28 0:00
+			-9:00	NT_YK	Y%sT	1973 Oct 28  0:00
 			-8:00	NT_YK	P%sT	1980
 			-8:00	Canada	P%sT
 
@@ -2188,9 +2146,8 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # From Paul Eggert (2001-03-05):
 # The Investigation and Analysis Service of the
 # Mexican Library of Congress (MLoC) has published a
-# 
 # history of Mexican local time (in Spanish)
-# .
+# http://www.cddhcu.gob.mx/bibliot/publica/inveyana/polisoc/horver/
 #
 # Here are the discrepancies between Shanks & Pottenger (S&P) and the MLoC.
 # (In all cases we go with the MLoC.)
@@ -2235,9 +2192,8 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # -------------- End Forwarded Message --------------
 # From Paul Eggert (1996-06-12):
 # For an English translation of the decree, see
-# 
 # "Diario Oficial: Time Zone Changeover" (1996-01-04).
-# 
+# http://mexico-travel.com/extra/timezone_eng.html
 
 # From Rives McDow (1998-10-08):
 # The State of Quintana Roo has reverted back to central STD and DST times
@@ -2249,7 +2205,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # savings time so as to stay on the same time zone as the southern part of
 # Arizona year round.
 
-# From Jesper Norgaard, translating
+# From Jesper Nørgaard, translating
 #  (2001-01-17):
 # In Oaxaca, the 55.000 teachers from the Section 22 of the National
 # Syndicate of Education Workers, refuse to apply daylight saving each
@@ -2262,7 +2218,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # January 17, 2000 - The Energy Secretary, Ernesto Martens, announced
 # that Summer Time will be reduced from seven to five months, starting
 # this year....
-# 
+# http://www.publico.com.mx/scripts/texto3.asp?action=pagina&pag=21&pos=p&secc=naci&date=01/17/2001
 # [translated], says "summer time will ... take effect on the first Sunday
 # in May, and end on the last Sunday of September.
 
@@ -2270,23 +2226,22 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # The 2001-01-24 traditional Washington Post contained the page one
 # story "Timely Issue Divides Mexicans."...
 # http://www.washingtonpost.com/wp-dyn/articles/A37383-2001Jan23.html
-# ... Mexico City Mayor Lopez Obrador "...is threatening to keep
+# ... Mexico City Mayor López Obrador "...is threatening to keep
 # Mexico City and its 20 million residents on a different time than
-# the rest of the country..." In particular, Lopez Obrador would abolish
+# the rest of the country..." In particular, López Obrador would abolish
 # observation of Daylight Saving Time.
 
-# 
 # Official statute published by the Energy Department
-#  (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
-# and Sonora with no DST.  This was reported by Jesper Norgaard (2001-02-03).
+# http://www.conae.gob.mx/ahorro/decretohorver2001.html#decre
+# (2001-02-01) shows Baja and Chihauhua as still using US DST rules,
+# and Sonora with no DST.  This was reported by Jesper Nørgaard (2001-02-03).
 
 # From Paul Eggert (2001-03-03):
 #
-# 
+# http://www.latimes.com/news/nation/20010303/t000018766.html
 # James F. Smith writes in today's LA Times
-# 
 # * Sonora will continue to observe standard time.
-# * Last week Mexico City's mayor Andres Manuel Lopez Obrador decreed that
+# * Last week Mexico City's mayor Andrés Manuel López Obrador decreed that
 #   the Federal District will not adopt DST.
 # * 4 of 16 district leaders announced they'll ignore the decree.
 # * The decree does not affect federal-controlled facilities including
@@ -2294,7 +2249,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 #
 # For now we'll assume that the Federal District will bow to federal rules.
 
-# From Jesper Norgaard (2001-04-01):
+# From Jesper Nørgaard (2001-04-01):
 # I found some references to the Mexican application of daylight
 # saving, which modifies what I had already sent you, stating earlier
 # that a number of northern Mexican states would go on daylight
@@ -2303,7 +2258,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # saving all year) will follow the original decree of president
 # Vicente Fox, starting daylight saving May 6, 2001 and ending
 # September 30, 2001.
-# References: "Diario de Monterrey" 
+# References: "Diario de Monterrey" 
 # Palabra  (2001-03-31)
 
 # From Reuters (2001-09-04):
@@ -2315,7 +2270,7 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # standard time. "This is so residents of the Federal District are not
 # subject to unexpected time changes," a statement from the court said.
 
-# From Jesper Norgaard Welen (2002-03-12):
+# From Jesper Nørgaard Welen (2002-03-12):
 # ... consulting my local grocery store(!) and my coworkers, they all insisted
 # that a new decision had been made to reinstate US style DST in Mexico....
 # http://www.conae.gob.mx/ahorro/horaver2001_m1_2002.html (2002-02-20)
@@ -2329,48 +2284,36 @@ Zone America/Dawson	-9:17:40 -	LMT	1900 Aug 20
 # > the United States.
 # Now this has passed both the Congress and the Senate, so starting from
 # 2010, some border regions will be the same:
-# 
 # http://www.signonsandiego.com/news/2009/dec/28/clocks-will-match-both-sides-border/
-# 
-# 
 # http://www.elmananarey.com/diario/noticia/nacional/noticias/empatan_horario_de_frontera_con_eu/621939
-# 
 # (Spanish)
 #
 # Could not find the new law text, but the proposed law text changes are here:
-# 
 # http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/20091210-V.pdf
-# 
 # (Gaceta Parlamentaria)
 #
 # There is also a list of the votes here:
-# 
 # http://gaceta.diputados.gob.mx/Gaceta/61/2009/dic/V2-101209.html
-# 
 #
 # Our page:
-# 
 # http://www.timeanddate.com/news/time/north-mexico-dst-change.html
-# 
 
 # From Arthur David Olson (2010-01-20):
 # The page
-# 
 # http://dof.gob.mx/nota_detalle.php?codigo=5127480&fecha=06/01/2010
-# 
 # includes this text:
 # En los municipios fronterizos de Tijuana y Mexicali en Baja California;
-# Juárez y Ojinaga en Chihuahua; Acuña y Piedras Negras en Coahuila;
-# Anáhuac en Nuevo León; y Nuevo Laredo, Reynosa y Matamoros en
-# Tamaulipas, la aplicación de este horario estacional surtirá efecto
-# desde las dos horas del segundo domingo de marzo y concluirá a las dos
+# Juárez y Ojinaga en Chihuahua; Acuña y Piedras Negras en Coahuila;
+# Anáhuac en Nuevo León; y Nuevo Laredo, Reynosa y Matamoros en
+# Tamaulipas, la aplicación de este horario estacional surtirá efecto
+# desde las dos horas del segundo domingo de marzo y concluirá a las dos
 # horas del primer domingo de noviembre.
 # En los municipios fronterizos que se encuentren ubicados en la franja
-# fronteriza norte en el territorio comprendido entre la línea
-# internacional y la línea paralela ubicada a una distancia de veinte
-# kilómetros, así como la Ciudad de Ensenada, Baja California, hacia el
-# interior del país, la aplicación de este horario estacional surtirá
-# efecto desde las dos horas del segundo domingo de marzo y concluirá a
+# fronteriza norte en el territorio comprendido entre la línea
+# internacional y la línea paralela ubicada a una distancia de veinte
+# kilómetros, así como la Ciudad de Ensenada, Baja California, hacia el
+# interior del país, la aplicación de este horario estacional surtirá
+# efecto desde las dos horas del segundo domingo de marzo y concluirá a
 # las dos horas del primer domingo de noviembre.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -2389,39 +2332,39 @@ Rule	Mexico	2001	only	-	Sep	lastSun	2:00	0	S
 Rule	Mexico	2002	max	-	Apr	Sun>=1	2:00	1:00	D
 Rule	Mexico	2002	max	-	Oct	lastSun	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-# Quintana Roo
+# Quintana Roo; represented by Cancún
 Zone America/Cancun	-5:47:04 -	LMT	1922 Jan  1  0:12:56
 			-6:00	-	CST	1981 Dec 23
 			-5:00	Mexico	E%sT	1998 Aug  2  2:00
 			-6:00	Mexico	C%sT
-# Campeche, Yucatan
+# Campeche, Yucatán; represented by Mérida
 Zone America/Merida	-5:58:28 -	LMT	1922 Jan  1  0:01:32
 			-6:00	-	CST	1981 Dec 23
 			-5:00	-	EST	1982 Dec  2
 			-6:00	Mexico	C%sT
-# Coahuila, Durango, Nuevo Leon, Tamaulipas (near US border)
+# Coahuila, Durango, Nuevo León, Tamaulipas (near US border)
 Zone America/Matamoros	-6:40:00 -	LMT	1921 Dec 31 23:20:00
 			-6:00	-	CST	1988
 			-6:00	US	C%sT	1989
 			-6:00	Mexico	C%sT	2010
 			-6:00	US	C%sT
-# Coahuila, Durango, Nuevo Leon, Tamaulipas (away from US border)
+# Coahuila, Durango, Nuevo León, Tamaulipas (away from US border)
 Zone America/Monterrey	-6:41:16 -	LMT	1921 Dec 31 23:18:44
 			-6:00	-	CST	1988
 			-6:00	US	C%sT	1989
 			-6:00	Mexico	C%sT
 # Central Mexico
-Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1 0:23:24
+Zone America/Mexico_City -6:36:36 -	LMT	1922 Jan  1  0:23:24
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
 			-7:00	-	MST	1931 May  1 23:00
 			-6:00	-	CST	1931 Oct
 			-7:00	-	MST	1932 Apr  1
-			-6:00	Mexico	C%sT	2001 Sep 30 02:00
+			-6:00	Mexico	C%sT	2001 Sep 30  2:00
 			-6:00	-	CST	2002 Feb 20
 			-6:00	Mexico	C%sT
 # Chihuahua (near US border)
-Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan 1 0:02:20
+Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan  1  0:02:20
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
 			-7:00	-	MST	1931 May  1 23:00
@@ -2429,7 +2372,7 @@ Zone America/Ojinaga	-6:57:40 -	LMT	1922 Jan 1 0:02:20
 			-7:00	-	MST	1932 Apr  1
 			-6:00	-	CST	1996
 			-6:00	Mexico	C%sT	1998
-			-6:00	-	CST	1998 Apr Sun>=1 3:00
+			-6:00	-	CST	1998 Apr Sun>=1  3:00
 			-7:00	Mexico	M%sT	2010
 			-7:00	US	M%sT
 # Chihuahua (away from US border)
@@ -2441,7 +2384,7 @@ Zone America/Chihuahua	-7:04:20 -	LMT	1921 Dec 31 23:55:40
 			-7:00	-	MST	1932 Apr  1
 			-6:00	-	CST	1996
 			-6:00	Mexico	C%sT	1998
-			-6:00	-	CST	1998 Apr Sun>=1 3:00
+			-6:00	-	CST	1998 Apr Sun>=1  3:00
 			-7:00	Mexico	M%sT
 # Sonora
 Zone America/Hermosillo	-7:23:52 -	LMT	1921 Dec 31 23:36:08
@@ -2457,42 +2400,33 @@ Zone America/Hermosillo	-7:23:52 -	LMT	1921 Dec 31 23:36:08
 			-7:00	-	MST
 
 # From Alexander Krivenyshev (2010-04-21):
-# According to news, Bahía de Banderas (Mexican state of Nayarit)
+# According to news, Bahía de Banderas (Mexican state of Nayarit)
 # changed time zone UTC-7 to new time zone UTC-6 on April 4, 2010 (to
 # share the same time zone as nearby city Puerto Vallarta, Jalisco).
 #
 # (Spanish)
-# Bahía de Banderas homologa su horario al del centro del
-# país, a partir de este domingo
-# 
+# Bahía de Banderas homologa su horario al del centro del
+# país, a partir de este domingo
 # http://www.nayarit.gob.mx/notes.asp?id=20748
-# 
 #
-# Bahía de Banderas homologa su horario con el del Centro del
-# País
-# 
-# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50"
-# 
+# Bahía de Banderas homologa su horario con el del Centro del
+# País
+# http://www.bahiadebanderas.gob.mx/principal/index.php?option=com_content&view=article&id=261:bahia-de-banderas-homologa-su-horario-con-el-del-centro-del-pais&catid=42:comunicacion-social&Itemid=50
 #
 # (English)
-# Puerto Vallarta and Bahía de Banderas: One Time Zone
-# 
+# Puerto Vallarta and Bahía de Banderas: One Time Zone
 # http://virtualvallarta.com/puertovallarta/puertovallarta/localnews/2009-12-03-Puerto-Vallarta-and-Bahia-de-Banderas-One-Time-Zone.shtml
-# 
-#
-# or
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_mexico08.html
-# 
 #
 # "Mexico's Senate approved the amendments to the Mexican Schedule System that
-# will allow Bahía de Banderas and Puerto Vallarta to share the same time
+# will allow Bahía de Banderas and Puerto Vallarta to share the same time
 # zone ..."
 # Baja California Sur, Nayarit, Sinaloa
 
 # From Arthur David Olson (2010-05-01):
 # Use "Bahia_Banderas" to keep the name to fourteen characters.
 
+# Mazatlán
 Zone America/Mazatlan	-7:05:40 -	LMT	1921 Dec 31 23:54:20
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
@@ -2504,6 +2438,7 @@ Zone America/Mazatlan	-7:05:40 -	LMT	1921 Dec 31 23:54:20
 			-8:00	-	PST	1970
 			-7:00	Mexico	M%sT
 
+# Bahía de Banderas
 Zone America/Bahia_Banderas	-7:01:00 -	LMT	1921 Dec 31 23:59:00
 			-7:00	-	MST	1927 Jun 10 23:00
 			-6:00	-	CST	1930 Nov 15
@@ -2513,7 +2448,7 @@ Zone America/Bahia_Banderas	-7:01:00 -	LMT	1921 Dec 31 23:59:00
 			-6:00	-	CST	1942 Apr 24
 			-7:00	-	MST	1949 Jan 14
 			-8:00	-	PST	1970
-			-7:00	Mexico	M%sT	2010 Apr 4 2:00
+			-7:00	Mexico	M%sT	2010 Apr  4  2:00
 			-6:00	Mexico	C%sT
 
 # Baja California (near US border)
@@ -2560,7 +2495,7 @@ Zone America/Santa_Isabel	-7:39:28 -	LMT	1922 Jan  1  0:20:32
 # America/Tijuana only in that it did not observe DST from 1976
 # through 1995.  This was as per Shanks (1999).  But Shanks & Pottenger say
 # Ensenada did not observe DST from 1948 through 1975.  Guy Harris reports
-# that the 1987 OAG says "Only Ensenada, Mexicale, San Felipe and
+# that the 1987 OAG says "Only Ensenada, Mexicali, San Felipe and
 # Tijuana observe DST," which agrees with Shanks & Pottenger but implies that
 # DST-observance was a town-by-town matter back then.  This concerns
 # data after 1970 so most likely there should be at least one Zone
@@ -2573,7 +2508,7 @@ Zone America/Santa_Isabel	-7:39:28 -	LMT	1922 Jan  1  0:20:32
 ###############################################################################
 
 # Anguilla
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Antigua and Barbuda
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
@@ -2609,8 +2544,8 @@ Rule	Barb	1978	1980	-	Apr	Sun>=15	2:00	1:00	D
 Rule	Barb	1979	only	-	Sep	30	2:00	0	S
 Rule	Barb	1980	only	-	Sep	25	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Barbados	-3:58:29 -	LMT	1924		# Bridgetown
-			-3:58:29 -	BMT	1932	  # Bridgetown Mean Time
+Zone America/Barbados	-3:58:29 -	LMT	1924 # Bridgetown
+			-3:58:29 -	BMT	1932 # Bridgetown Mean Time
 			-4:00	Barb	A%sT
 
 # Belize
@@ -2640,20 +2575,20 @@ Zone	America/Belize	-5:52:48 -	LMT	1912 Apr
 # http://www.theroyalgazette.com/apps/pbcs.dll/article?AID=/20060529/NEWS/105290135
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1 2:00    # Hamilton
-			-4:00	-	AST	1974 Apr 28 2:00
+Zone Atlantic/Bermuda	-4:19:18 -	LMT	1930 Jan  1  2:00 # Hamilton
+			-4:00	-	AST	1974 Apr 28  2:00
 			-4:00	Canada	A%sT	1976
 			-4:00	US	A%sT
 
 # Cayman Is
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Cayman	-5:25:32 -	LMT	1890		# Georgetown
-			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
+Zone	America/Cayman	-5:25:32 -	LMT	1890     # Georgetown
+			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
 			-5:00	-	EST
 
 # Costa Rica
 
-# Milne gives -5:36:13.3 as San Jose mean time; round to nearest.
+# Milne gives -5:36:13.3 as San José mean time; round to nearest.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	CR	1979	1980	-	Feb	lastSun	0:00	1:00	D
@@ -2663,10 +2598,10 @@ Rule	CR	1991	1992	-	Jan	Sat>=15	0:00	1:00	D
 # go with Shanks & Pottenger.
 Rule	CR	1991	only	-	Jul	 1	0:00	0	S
 Rule	CR	1992	only	-	Mar	15	0:00	0	S
-# There are too many San Joses elsewhere, so we'll use 'Costa Rica'.
+# There are too many San Josés elsewhere, so we'll use 'Costa Rica'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
-			-5:36:13 -	SJMT	1921 Jan 15 # San Jose Mean Time
+Zone America/Costa_Rica	-5:36:13 -	LMT	1890        # San José
+			-5:36:13 -	SJMT	1921 Jan 15 # San José Mean Time
 			-6:00	CR	C%sT
 # Coco
 # no information; probably like America/Costa_Rica
@@ -2685,8 +2620,8 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # During the game, play-by-play announcer Jim Hunter noted that
 # "We'll be losing two hours of sleep...Cuba switched to Daylight Saving
 # Time today."  (The "two hour" remark referred to losing one hour of
-# sleep on 1999-03-28--when the announcers were in Cuba as it switched
-# to DST--and one more hour on 1999-04-04--when the announcers will have
+# sleep on 1999-03-28 - when the announcers were in Cuba as it switched
+# to DST - and one more hour on 1999-04-04 - when the announcers will have
 # returned to Baltimore, which switches on that date.)
 
 # From Steffen Thorsen (2013-11-11):
@@ -2708,16 +2643,16 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # adjustment in Cuba.  We will stay in daylight saving time:
 # http://www.granma.cu/espanol/2005/noviembre/mier9/horario.html
 
-# From Jesper Norgaard Welen (2006-10-21):
+# From Jesper Nørgaard Welen (2006-10-21):
 # An article in GRANMA INTERNACIONAL claims that Cuba will end
 # the 3 years of permanent DST next weekend, see
 # http://www.granma.cu/ingles/2006/octubre/lun16/43horario.html
 # "On Saturday night, October 28 going into Sunday, October 29, at 01:00,
-# watches should be set back one hour -- going back to 00:00 hours -- returning
+# watches should be set back one hour - going back to 00:00 hours - returning
 # to the normal schedule....
 
 # From Paul Eggert (2007-03-02):
-# http://www.granma.cubaweb.cu/english/news/art89.html, dated yesterday,
+# , dated yesterday,
 # says Cuban clocks will advance at midnight on March 10.
 # For lack of better information, assume Cuba will use US rules,
 # except that it switches at midnight standard time as usual.
@@ -2731,10 +2666,10 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # http://www.prensalatina.com.mx/article.asp?ID=%7B4CC32C1B-A9F7-42FB-8A07-8631AFC923AF%7D&language=ES
 # http://actualidad.terra.es/sociedad/articulo/cuba_llama_ahorrar_energia_cambio_1957044.htm
 #
-# From Alex Kryvenishev (2007-10-25):
+# From Alex Krivenyshev (2007-10-25):
 # Here is also article from Granma (Cuba):
 #
-# [Regira] el Horario Normal desde el [proximo] domingo 28 de octubre
+# Regirá el Horario Normal desde el próximo domingo 28 de octubre
 # http://www.granma.cubaweb.cu/2007/10/24/nacional/artic07.html
 #
 # http://www.worldtimezone.com/dst_news/dst_news_cuba03.html
@@ -2742,23 +2677,18 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # From Arthur David Olson (2008-03-09):
 # I'm in Maryland which is now observing United States Eastern Daylight
 # Time. At 9:44 local time I used RealPlayer to listen to
-# 
 # http://media.enet.cu/radioreloj
-# , a Cuban information station, and heard
+# a Cuban information station, and heard
 # the time announced as "ocho cuarenta y cuatro" ("eight forty-four"),
 # indicating that Cuba is still on standard time.
 
 # From Steffen Thorsen (2008-03-12):
 # It seems that Cuba will start DST on Sunday, 2007-03-16...
 # It was announced yesterday, according to this source (in Spanish):
-# 
 # http://www.nnc.cubaweb.cu/marzo-2008/cien-1-11-3-08.htm
-# 
 #
 # Some more background information is posted here:
-# 
 # http://www.timeanddate.com/news/time/cuba-starts-dst-march-16.html
-# 
 #
 # The article also says that Cuba has been observing DST since 1963,
 # while Shanks (and tzdata) has 1965 as the first date (except in the
@@ -2768,18 +2698,14 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # change some historic records as well.
 #
 # One example:
-# 
 # http://www.radiohc.cu/espanol/noticias/mar07/11mar/hor.htm
-# 
 
-# From Jesper Norgaard Welen (2008-03-13):
+# From Jesper Nørgaard Welen (2008-03-13):
 # The Cuban time change has just been confirmed on the most authoritative
 # web site, the Granma.  Please check out
-# 
 # http://www.granma.cubaweb.cu/2008/03/13/nacional/artic10.html
-# 
 #
-# Basically as expected after Steffen Thorsens information, the change
+# Basically as expected after Steffen Thorsen's information, the change
 # will take place midnight between Saturday and Sunday.
 
 # From Arthur David Olson (2008-03-12):
@@ -2790,18 +2716,14 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # midnight between Saturday, March 07, 2009 and Sunday, March 08, 2009-
 # not on midnight March 14 / March 15 as previously thought.
 #
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_cuba05.html
 # (in Spanish)
-# 
 
 # From Arthur David Olson (2009-03-09)
 # I listened over the Internet to
-# 
 # http://media.enet.cu/readioreloj
-# 
 # this morning; when it was 10:05 a. m. here in Bethesda, Maryland the
-# the time was announced as "diez cinco"--the same time as here, indicating
+# the time was announced as "diez cinco" - the same time as here, indicating
 # that has indeed switched to DST. Assume second Sunday from 2009 forward.
 
 # From Steffen Thorsen (2011-03-08):
@@ -2810,42 +2732,30 @@ Zone America/Costa_Rica	-5:36:13 -	LMT	1890		# San Jose
 # changed at all).
 #
 # Source:
-# 
 # http://granma.co.cu/2011/03/08/nacional/artic01.html
-# 
 #
 # Our info:
-# 
 # http://www.timeanddate.com/news/time/cuba-starts-dst-2011.html
-# 
 #
 # From Steffen Thorsen (2011-10-30)
 # Cuba will end DST two weeks later this year. Instead of going back
 # tonight, it has been delayed to 2011-11-13 at 01:00.
 #
 # One source (Spanish)
-# 
 # http://www.radioangulo.cu/noticias/cuba/17105-cuba-restablecera-el-horario-del-meridiano-de-greenwich.html
-# 
 #
 # Our page:
-# 
 # http://www.timeanddate.com/news/time/cuba-time-changes-2011.html
-# 
 #
 # From Steffen Thorsen (2012-03-01)
 # According to Radio Reloj, Cuba will start DST on Midnight between March
 # 31 and April 1.
 #
 # Radio Reloj has the following info (Spanish):
-# 
 # http://www.radioreloj.cu/index.php/noticias-radio-reloj/71-miscelaneas/7529-cuba-aplicara-el-horario-de-verano-desde-el-1-de-abril
-# 
 #
 # Our info on it:
-# 
 # http://www.timeanddate.com/news/time/cuba-starts-dst-2012.html
-# 
 
 # From Steffen Thorsen (2012-11-03):
 # Radio Reloj and many other sources report that Cuba is changing back
@@ -2901,7 +2811,7 @@ Zone	America/Havana	-5:29:28 -	LMT	1890
 			-5:00	Cuba	C%sT
 
 # Dominica
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Dominican Republic
 
@@ -2934,8 +2844,8 @@ Rule	DR	1972	1974	-	Jan	21	0:00	0	S
 Zone America/Santo_Domingo -4:39:36 -	LMT	1890
 			-4:40	-	SDMT	1933 Apr  1 12:00 # S. Dom. MT
 			-5:00	DR	E%sT	1974 Oct 27
-			-4:00	-	AST	2000 Oct 29 02:00
-			-5:00	US	E%sT	2000 Dec  3 01:00
+			-4:00	-	AST	2000 Oct 29  2:00
+			-5:00	US	E%sT	2000 Dec  3  1:00
 			-4:00	-	AST
 
 # El Salvador
@@ -2946,20 +2856,20 @@ Rule	Salv	1987	1988	-	Sep	lastSun	0:00	0	S
 # There are too many San Salvadors elsewhere, so use America/El_Salvador
 # instead of America/San_Salvador.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/El_Salvador -5:56:48 -	LMT	1921		# San Salvador
+Zone America/El_Salvador -5:56:48 -	LMT	1921 # San Salvador
 			-6:00	Salv	C%sT
 
 # Grenada
 # Guadeloupe
-# St Barthelemy
+# St Barthélemy
 # St Martin (French part)
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Guatemala
 #
 # From Gwillim Law (2006-04-22), after a heads-up from Oscar van Vlijmen:
 # Diario Co Latino, at
-# http://www.diariocolatino.com/internacionales/detalles.asp?NewsID=8079,
+# ,
 # says in an article dated 2006-04-19 that the Guatemalan government had
 # decided on that date to advance official time by 60 minutes, to lessen the
 # impact of the elevated cost of oil....  Daylight saving time will last from
@@ -2967,7 +2877,7 @@ Zone America/El_Salvador -5:56:48 -	LMT	1921		# San Salvador
 # From Paul Eggert (2006-06-22):
 # The Ministry of Energy and Mines, press release CP-15/2006
 # (2006-04-19), says DST ends at 24:00.  See
-# .
+# http://www.sieca.org.gt/Sitio_publico/Energeticos/Doc/Medidas/Cambio_Horario_Nac_190406.pdf
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
 Rule	Guat	1973	only	-	Nov	25	0:00	1:00	D
@@ -2984,11 +2894,10 @@ Zone America/Guatemala	-6:02:04 -	LMT	1918 Oct 5
 
 # Haiti
 # From Gwillim Law (2005-04-15):
-# Risto O. Nykanen wrote me that Haiti is now on DST.
-# I searched for confirmation, and I found a
-#  press release
+# Risto O. Nykänen wrote me that Haiti is now on DST.
+# I searched for confirmation, and I found a press release
 # on the Web page of the Haitian Consulate in Chicago (2005-03-31),
-# .  Translated from French, it says:
+# .  Translated from French, it says:
 #
 #  "The Prime Minister's Communication Office notifies the public in general
 #   and the press in particular that, following a decision of the Interior
@@ -3065,14 +2974,14 @@ Zone America/Port-au-Prince -4:49:20 -	LMT	1890
 #  that Manuel Zelaya, the president
 # of Honduras, refused to back down on this.
 
-# From Jesper Norgaard Welen (2006-08-08):
+# From Jesper Nørgaard Welen (2006-08-08):
 # It seems that Honduras has returned from DST to standard time this Monday at
 # 00:00 hours (prolonging Sunday to 25 hours duration).
 # http://www.worldtimezone.com/dst_news/dst_news_honduras04.html
 
 # From Paul Eggert (2006-08-08):
-# Also see Diario El Heraldo, The country returns to standard time (2006-08-08)
-# .
+# Also see Diario El Heraldo, The country returns to standard time (2006-08-08).
+# http://www.elheraldo.hn/nota.php?nid=54941&sec=12
 # It mentions executive decree 18-2006.
 
 # From Steffen Thorsen (2006-08-17):
@@ -3100,22 +3009,22 @@ Zone America/Tegucigalpa -5:48:52 -	LMT	1921 Apr
 # unspecified official document, and says "This time is used throughout the
 # island".  Go with Milne.  Round to the nearest second as required by zic.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Jamaica	-5:07:11 -	LMT	1890		# Kingston
+Zone	America/Jamaica	-5:07:11 -	LMT	1890        # Kingston
 			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
-			-5:00	-	EST	1974 Apr 28 2:00
+			-5:00	-	EST	1974 Apr 28  2:00
 			-5:00	US	E%sT	1984
 			-5:00	-	EST
 
 # Martinique
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Martinique	-4:04:20 -      LMT	1890		# Fort-de-France
-			-4:04:20 -	FFMT	1911 May     # Fort-de-France MT
+Zone America/Martinique	-4:04:20 -      LMT	1890        # Fort-de-France
+			-4:04:20 -	FFMT	1911 May    # Fort-de-France MT
 			-4:00	-	AST	1980 Apr  6
 			-4:00	1:00	ADT	1980 Sep 28
 			-4:00	-	AST
 
 # Montserrat
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Nicaragua
 #
@@ -3138,27 +3047,27 @@ Zone America/Martinique	-4:04:20 -      LMT	1890		# Fort-de-France
 # From Gwillim Law (2005-04-21):
 # The Associated Press story on the time change, which can be found at
 # http://www.lapalmainteractivo.com/guias/content/gen/ap/America_Latina/AMC_GEN_NICARAGUA_HORA.html
-# and elsewhere, says (fifth paragraph, translated from Spanish):  "The last
+# and elsewhere, says (fifth paragraph, translated from Spanish): "The last
 # time that a change of clocks was applied to save energy was in the year 2000
-# during the Arnoldo Aleman administration."...
+# during the Arnoldo Alemán administration."...
 # The northamerica file says that Nicaragua has been on UTC-6 continuously
 # since December 1998.  I wasn't able to find any details of Nicaraguan time
 # changes in 2000.  Perhaps a note could be added to the northamerica file, to
 # the effect that we have indirect evidence that DST was observed in 2000.
 #
-# From Jesper Norgaard Welen (2005-11-02):
+# From Jesper Nørgaard Welen (2005-11-02):
 # Nicaragua left DST the 2005-10-02 at 00:00 (local time).
 # http://www.presidencia.gob.ni/presidencia/files_index/secretaria/comunicados/2005/septiembre/26septiembre-cambio-hora.htm
 # (2005-09-26)
 #
-# From Jesper Norgaard Welen (2006-05-05):
+# From Jesper Nørgaard Welen (2006-05-05):
 # http://www.elnuevodiario.com.ni/2006/05/01/nacionales/18410
 # (my informal translation)
-# By order of the president of the republic, Enrique Bolanos, Nicaragua
+# By order of the president of the republic, Enrique Bolaños, Nicaragua
 # advanced by sixty minutes their official time, yesterday at 2 in the
-# morning, and will stay that way until 30.th. of september.
+# morning, and will stay that way until 30th of September.
 #
-# From Jesper Norgaard Welen (2006-09-30):
+# From Jesper Nørgaard Welen (2006-09-30):
 # http://www.presidencia.gob.ni/buscador_gaceta/BD/DECRETOS/2006/D-063-2006P-PRN-Cambio-Hora.pdf
 # My informal translation runs:
 # The natural sun time is restored in all the national territory, in that the
@@ -3176,7 +3085,7 @@ Zone	America/Managua	-5:45:08 -	LMT	1890
 			-5:45:12 -	MMT	1934 Jun 23 # Managua Mean Time?
 			-6:00	-	CST	1973 May
 			-5:00	-	EST	1975 Feb 16
-			-6:00	Nic	C%sT	1992 Jan  1 4:00
+			-6:00	Nic	C%sT	1992 Jan  1  4:00
 			-5:00	-	EST	1992 Sep 24
 			-6:00	-	CST	1993
 			-5:00	-	EST	1997
@@ -3185,36 +3094,36 @@ Zone	America/Managua	-5:45:08 -	LMT	1890
 # Panama
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Panama	-5:18:08 -	LMT	1890
-			-5:19:36 -	CMT	1908 Apr 22   # Colon Mean Time
+			-5:19:36 -	CMT	1908 Apr 22 # Colón Mean Time
 			-5:00	-	EST
 
 # Puerto Rico
 # There are too many San Juans elsewhere, so we'll use 'Puerto_Rico'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00    # San Juan
+Zone America/Puerto_Rico -4:24:25 -	LMT	1899 Mar 28 12:00 # San Juan
 			-4:00	-	AST	1942 May  3
 			-4:00	US	A%sT	1946
 			-4:00	-	AST
 
 # St Kitts-Nevis
 # St Lucia
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # St Pierre and Miquelon
 # There are too many St Pierres elsewhere, so we'll use 'Miquelon'.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15	# St Pierre
+Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15 # St Pierre
 			-4:00	-	AST	1980 May
 			-3:00	-	PMST	1987 # Pierre & Miquelon Time
 			-3:00	Canada	PM%sT
 
 # St Vincent and the Grenadines
-# See 'southamerica'.
+# See America/Port_of_Spain.
 
 # Turks and Caicos
 #
 # From Chris Dunn in
-# 
+# http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=415007
 # (2007-03-15): In the Turks & Caicos Islands (America/Grand_Turk) the
 # daylight saving dates for time changes have been adjusted to match
 # the recent U.S. change of dates.
@@ -3227,21 +3136,23 @@ Zone America/Miquelon	-3:44:40 -	LMT	1911 May 15	# St Pierre
 # Clocks are set back one hour at 2:00 a.m. local Daylight Saving Time"
 # indicating that the normal ET rules are followed.
 #
-# From Paul Eggert (2006-05-01):
-# Shanks & Pottenger say they use US DST rules, but IATA SSIM (1991/1998)
-# says they switch at midnight.  Go with Shanks & Pottenger.
+# From Paul Eggert (2014-08-19):
+# The 2014-08-13 Cabinet meeting decided to stay on UTC-4 year-round.  See:
+# http://tcweeklynews.com/daylight-savings-time-to-be-maintained-p5353-127.htm
+# Model this as a switch from EST/EDT to AST on 2014-11-02 at 02:00.
 #
-# Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-Rule	TC	1979	1986	-	Apr	lastSun	2:00	1:00	D
-Rule	TC	1979	2006	-	Oct	lastSun	2:00	0	S
-Rule	TC	1987	2006	-	Apr	Sun>=1	2:00	1:00	D
-Rule	TC	2007	max	-	Mar	Sun>=8	2:00	1:00	D
-Rule	TC	2007	max	-	Nov	Sun>=1	2:00	0	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Grand_Turk	-4:44:32 -	LMT	1890
-			-5:07:11 -	KMT	1912 Feb    # Kingston Mean Time
-			-5:00	TC	E%sT
+			-5:07:11 -	KMT	1912 Feb # Kingston Mean Time
+			-5:00	-	EST	1979
+			-5:00	US	E%sT	2014 Nov  2  2:00
+			-4:00	-	AST
 
 # British Virgin Is
 # Virgin Is
-# See 'southamerica'.
+# See America/Port_of_Spain.
+
+
+# Local Variables:
+# coding: utf-8
+# End:
diff --git a/jdk/make/data/tzdata/pacificnew b/jdk/make/data/tzdata/pacificnew
index 09000c3457a..9b9257a45fe 100644
--- a/jdk/make/data/tzdata/pacificnew
+++ b/jdk/make/data/tzdata/pacificnew
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
diff --git a/jdk/make/data/tzdata/southamerica b/jdk/make/data/tzdata/southamerica
index 02bf3bb6332..398ec0e4f06 100644
--- a/jdk/make/data/tzdata/southamerica
+++ b/jdk/make/data/tzdata/southamerica
@@ -21,13 +21,13 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
-# This data is by no means authoritative; if you think you know better,
+# This file is by no means authoritative; if you think you know better,
 # go ahead and edit the file (and please send any changes to
-# tz@iana.org for general use in the future).
+# tz@iana.org for general use in the future).  For more, please see
+# the file CONTRIBUTING in the tz distribution.
 
 # From Paul Eggert (2006-03-22):
 # A good source for time zone historical data outside the U.S. is
@@ -35,8 +35,8 @@
 # San Diego: ACS Publications, Inc. (2003).
 #
 # For data circa 1899, a common source is:
-# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94
-# .
+# Milne J. Civil time. Geogr J. 1899 Feb;13(2):173-94.
+# http://www.jstor.org/stable/1774359
 #
 # Gwillim Law writes that a good source
 # for recent time zone data is the International Air Transport
@@ -53,24 +53,24 @@
 #	I suggest the use of _Summer time_ instead of the more cumbersome
 #	_daylight-saving time_.  _Summer time_ seems to be in general use
 #	in Europe and South America.
-#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
+#	-- E O Cutler, _New York Times_ (1937-02-14), quoted in
 #	H L Mencken, _The American Language: Supplement I_ (1960), p 466
 #
 # Earlier editions of these tables also used the North American style
 # for time zones in Brazil, but this was incorrect, as Brazilians say
-# "summer time".  Reinaldo Goulart, a Sao Paulo businessman active in
+# "summer time".  Reinaldo Goulart, a São Paulo businessman active in
 # the railroad sector, writes (1999-07-06):
 #	The subject of time zones is currently a matter of discussion/debate in
-#	Brazil.  Let's say that "the Brasilia time" is considered the
-#	"official time" because Brasilia is the capital city.
-#	The other three time zones are called "Brasilia time "minus one" or
+#	Brazil.  Let's say that "the Brasília time" is considered the
+#	"official time" because Brasília is the capital city.
+#	The other three time zones are called "Brasília time "minus one" or
 #	"plus one" or "plus two".  As far as I know there is no such
 #	name/designation as "Eastern Time" or "Central Time".
 # So I invented the following (English-language) abbreviations for now.
 # Corrections are welcome!
 #		std	dst
 #	-2:00	FNT	FNST	Fernando de Noronha
-#	-3:00	BRT	BRST	Brasilia
+#	-3:00	BRT	BRST	Brasília
 #	-4:00	AMT	AMST	Amazon
 #	-5:00	ACT	ACST	Acre
 
@@ -84,7 +84,7 @@
 # Argentina: first Sunday in October to first Sunday in April since 1976.
 # Double Summer time from 1969 to 1974.  Switches at midnight.
 
-# From U. S. Naval Observatory (1988-01-199):
+# From U. S. Naval Observatory (1988-01-19):
 # ARGENTINA           3 H BEHIND   UTC
 
 # From Hernan G. Otero (1995-06-26):
@@ -118,7 +118,7 @@ Rule	Arg	1988	only	-	Dec	 1	0:00	1:00	S
 # From Hernan G. Otero (1995-06-26):
 # These corrections were contributed by InterSoft Argentina S.A.,
 # obtaining the data from the:
-# Talleres de Hidrografia Naval Argentina
+# Talleres de Hidrografía Naval Argentina
 # (Argentine Naval Hydrography Institute)
 Rule	Arg	1989	1993	-	Mar	Sun>=1	0:00	0	-
 Rule	Arg	1989	1992	-	Oct	Sun>=15	0:00	1:00	S
@@ -140,13 +140,13 @@ Rule	Arg	1999	only	-	Oct	Sun>=1	0:00	1:00	S
 Rule	Arg	2000	only	-	Mar	3	0:00	0	-
 #
 # From Peter Gradelski via Steffen Thorsen (2000-03-01):
-# We just checked with our Sao Paulo office and they say the government of
+# We just checked with our São Paulo office and they say the government of
 # Argentina decided not to become one of the countries that go on or off DST.
 # So Buenos Aires should be -3 hours from GMT at all times.
 #
-# From Fabian L. Arce Jofre (2000-04-04):
+# From Fabián L. Arce Jofré (2000-04-04):
 # The law that claimed DST for Argentina was derogated by President Fernando
-# de la Rua on March 2, 2000, because it would make people spend more energy
+# de la Rúa on March 2, 2000, because it would make people spend more energy
 # in the winter time, rather than less.  The change took effect on March 3.
 #
 # From Mariano Absatz (2001-06-06):
@@ -179,15 +179,13 @@ Rule	Arg	2000	only	-	Mar	3	0:00	0	-
 # that Argentina will use DST next year as well, from October to
 # March, although exact rules are not given.
 #
-# From Jesper Norgaard Welen (2007-12-26)
+# From Jesper Nørgaard Welen (2007-12-26)
 # The last hurdle of Argentina DST is over, the proposal was approved in
-# the lower chamber too (Deputados) with a vote 192 for and 2 against.
+# the lower chamber too (Diputados) with a vote 192 for and 2 against.
 # By the way thanks to Mariano Absatz and Daniel Mario Vega for the link to
 # the original scanned proposal, where the dates and the zero hours are
 # clear and unambiguous...This is the article about final approval:
-# 
 # http://www.lanacion.com.ar/politica/nota.asp?nota_id=973996
-# 
 #
 # From Paul Eggert (2007-12-22):
 # For dates after mid-2008, the following rules are my guesses and
@@ -197,13 +195,8 @@ Rule	Arg	2000	only	-	Mar	3	0:00	0	-
 # As per message from Carlos Alberto Fonseca Arauz (Nicaragua),
 # Argentina will start DST on Sunday October 19, 2008.
 #
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_argentina03.html
-# 
-# OR
-# 
 # http://www.impulsobaires.com.ar/nota.php?id=57832 (in spanish)
-# 
 
 # From Rodrigo Severo (2008-10-06):
 # Here is some info available at a Gentoo bug related to TZ on Argentina's DST:
@@ -212,48 +205,39 @@ Rule	Arg	2000	only	-	Mar	3	0:00	0	-
 # Hi, there is a problem with timezone-data-2008e and maybe with
 # timezone-data-2008f
 # Argentinian law [Number] 25.155 is no longer valid.
-# 
 # http://www.infoleg.gov.ar/infolegInternet/anexos/60000-64999/60036/norma.htm
-# 
 # The new one is law [Number] 26.350
-# 
 # http://www.infoleg.gov.ar/infolegInternet/anexos/135000-139999/136191/norma.htm
-# 
 # So there is no summer time in Argentina for now.
 
 # From Mariano Absatz (2008-10-20):
-# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST in Argentina
-# From 2008-10-19 until 2009-03-15
-# 
+# Decree 1693/2008 applies Law 26.350 for the summer 2008/2009 establishing DST
+# in Argentina from 2008-10-19 until 2009-03-15.
 # http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=16102008&pi=3&pf=4&s=0&sec=01
-# 
 #
-# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer 2008/2009:
-# Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La Pampa, Neuquen, Rio Negro, Chubut, Santa Cruz
-# and Tierra del Fuego
-# 
+
+# Decree 1705/2008 excepting 12 Provinces from applying DST in the summer
+# 2008/2009: Catamarca, La Rioja, Mendoza, Salta, San Juan, San Luis, La
+# Pampa, Neuquén, Rio Negro, Chubut, Santa Cruz and Tierra del Fuego
 # http://www.boletinoficial.gov.ar/Bora.Portal/CustomControls/PdfContent.aspx?fp=17102008&pi=1&pf=1&s=0&sec=01
-# 
 #
-# Press release 235 dated Saturday October 18th, from the Government of the Province of Jujuy saying
-# it will not apply DST either (even when it was not included in Decree 1705/2008)
-# 
+# Press release 235 dated Saturday October 18th, from the Government of the
+# Province of Jujuy saying it will not apply DST either (even when it was not
+# included in Decree 1705/2008).
 # http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc
-# 
 
 # From fullinet (2009-10-18):
 # As announced in
-# 
 # http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356
-# 
-# (an official .gob.ar) under title: "Sin Cambio de Hora" (english: "No hour change")
+# (an official .gob.ar) under title: "Sin Cambio de Hora"
+# (English: "No hour change").
 #
-# "Por el momento, el Gobierno Nacional resolvio no modificar la hora
-# oficial, decision que estaba en estudio para su implementacion el
-# domingo 18 de octubre. Desde el Ministerio de Planificacion se anuncio
-# que la Argentina hoy, en estas condiciones meteorologicas, no necesita
-# la modificacion del huso horario, ya que 2009 nos encuentra con
-# crecimiento en la produccion y distribucion energetica."
+# "Por el momento, el Gobierno Nacional resolvió no modificar la hora
+# oficial, decisión que estaba en estudio para su implementación el
+# domingo 18 de octubre. Desde el Ministerio de Planificación se anunció
+# que la Argentina hoy, en estas condiciones meteorológicas, no necesita
+# la modificación del huso horario, ya que 2009 nos encuentra con
+# crecimiento en la producción y distribución energética."
 
 Rule	Arg	2007	only	-	Dec	30	0:00	1:00	S
 Rule	Arg	2008	2009	-	Mar	Sun>=15	0:00	0	-
@@ -267,10 +251,10 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # It's Law No. 7,210.  This change is due to a public power emergency, so for
 # now we'll assume it's for this year only.
 #
-# From Paul Eggert (2006-03-22):
-# 
-# Hora de verano para la Republica Argentina (2003-06-08)
-#  says that standard time in Argentina from 1894-10-31
+# From Paul Eggert (2014-08-09):
+# Hora de verano para la República Argentina
+# http://buenasiembra.com.ar/esoterismo/astrologia/hora-de-verano-de-la-republica-argentina-27.html
+# says that standard time in Argentina from 1894-10-31
 # to 1920-05-01 was -4:16:48.25.  Go with this more-precise value
 # over Shanks & Pottenger.
 #
@@ -285,10 +269,10 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # time in October 17th.
 #
 # Catamarca, Chubut, La Rioja, San Juan, San Luis, Santa Cruz,
-# Tierra del Fuego, Tucuman.
+# Tierra del Fuego, Tucumán.
 #
 # From Mariano Absatz (2004-06-14):
-# ... this weekend, the Province of Tucuman decided it'd go back to UTC-03:00
+# ... this weekend, the Province of Tucumán decided it'd go back to UTC-03:00
 # yesterday midnight (that is, at 24:00 Saturday 12th), since the people's
 # annoyance with the change is much higher than the power savings obtained....
 #
@@ -323,49 +307,38 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # Here are articles that Argentina Province San Luis is planning to end DST
 # as earlier as upcoming Monday January 21, 2008 or February 2008:
 #
-# Provincia argentina retrasa reloj y marca diferencia con resto del pais
+# Provincia argentina retrasa reloj y marca diferencia con resto del país
 # (Argentine Province delayed clock and mark difference with the rest of the
 # country)
-# 
 # http://cl.invertia.com/noticias/noticia.aspx?idNoticia=200801171849_EFE_ET4373&idtel
-# 
 #
 # Es inminente que en San Luis atrasen una hora los relojes
 # (It is imminent in San Luis clocks one hour delay)
-# 
-# http://www.lagaceta.com.ar/vernotae.asp?id_nota=253414
-# 
-#
-# 
+# http://www.lagaceta.com.ar/nota/253414/Economia/Es-inminente-que-en-San-Luis-atrasen-una-hora-los-relojes.html
 # http://www.worldtimezone.net/dst_news/dst_news_argentina02.html
-# 
 
-# From Jesper Norgaard Welen (2008-01-18):
+# From Jesper Nørgaard Welen (2008-01-18):
 # The page of the San Luis provincial government
-# 
 # http://www.sanluis.gov.ar/notas.asp?idCanal=0&id=22812
-# 
 # confirms what Alex Krivenyshev has earlier sent to the tz
 # emailing list about that San Luis plans to return to standard
 # time much earlier than the rest of the country. It also
 # confirms that upon request the provinces San Juan and Mendoza
 # refused to follow San Luis in this change.
 #
-# The change is supposed to take place Monday the 21.st at 0:00
+# The change is supposed to take place Monday the 21st at 0:00
 # hours. As far as I understand it if this goes ahead, we need
 # a new timezone for San Luis (although there are also documented
 # independent changes in the southamerica file of San Luis in
 # 1990 and 1991 which has not been confirmed).
 
-# From Jesper Norgaard Welen (2008-01-25):
+# From Jesper Nørgaard Welen (2008-01-25):
 # Unfortunately the below page has become defunct, about the San Luis
 # time change. Perhaps because it now is part of a group of pages "Most
 # important pages of 2008."
 #
 # You can use
-# 
 # http://www.sanluis.gov.ar/notas.asp?idCanal=8141&id=22834
-# 
 # instead it seems. Or use "Buscador" from the main page of the San Luis
 # government, and fill in "huso" and click OK, and you will get 3 pages
 # from which the first one is identical to the above.
@@ -385,9 +358,9 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # back in 2004, when these provinces changed to UTC-4 for a few days, I
 # mailed them personally and never got an answer).
 
-# From Paul Eggert (2008-06-30):
-# Unless otherwise specified, data are from Shanks & Pottenger through 1992,
-# from the IATA otherwise.  As noted below, Shanks & Pottenger say that
+# From Paul Eggert (2014-08-12):
+# Unless otherwise specified, data entries are from Shanks & Pottenger through
+# 1992, from the IATA otherwise.  As noted below, Shanks & Pottenger say that
 # America/Cordoba split into 6 subregions during 1991/1992, one of which
 # was America/San_Luis, but we haven't verified this yet so for now we'll
 # keep America/Cordoba a single region rather than splitting it into the
@@ -399,14 +372,9 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # to utc-04:00 until the second Saturday in October...
 #
 # The press release is at
-# 
 # http://www.sanluis.gov.ar/SL/Paginas/NoticiaDetalle.asp?TemaId=1&InfoPrensaId=3102
-# 
-# (I couldn't find the decree, but
-# 
-# www.sanluis.gov.ar
-# 
-# is the official page for the Province Government).
+# (I couldn't find the decree, but www.sanluis.gov.ar
+# is the official page for the Province Government.)
 #
 # There's also a note in only one of the major national papers ...
 # http://www.lanacion.com.ar/nota.asp?nota_id=1107912
@@ -423,9 +391,7 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # ...the Province of San Luis is a case in itself.
 #
 # The Law at
-# 
 # is ambiguous because establishes a calendar from the 2nd Sunday in
 # October at 0:00 thru the 2nd Saturday in March at 24:00 and the
 # complement of that starting on the 2nd Sunday of March at 0:00 and
@@ -454,19 +420,15 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # ...
 
 # From Alexander Krivenyshev (2010-04-09):
-# According to news reports from El Diario de la Republica Province San
+# According to news reports from El Diario de la República Province San
 # Luis, Argentina (standard time UTC-04) will keep Daylight Saving Time
-# after April 11, 2010--will continue to have same time as rest of
+# after April 11, 2010 - will continue to have same time as rest of
 # Argentina (UTC-3) (no DST).
 #
-# Confirmaron la prórroga del huso horario de verano (Spanish)
-# 
+# Confirmaron la prórroga del huso horario de verano (Spanish)
 # http://www.eldiariodelarepublica.com/index.php?option=com_content&task=view&id=29383&Itemid=9
-# 
 # or (some English translation):
-# 
 # http://www.worldtimezone.com/dst_news/dst_news_argentina08.html
-# 
 
 # From Mariano Absatz (2010-04-12):
 # yes...I can confirm this...and given that San Luis keeps calling
@@ -478,7 +440,7 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # Perhaps San Luis operates on the legal fiction that it is at UTC-4
 # with perpetual summer time, but ordinary usage typically seems to
 # just say it's at UTC-3; see, for example,
-# .
+# http://es.wikipedia.org/wiki/Hora_oficial_argentina
 # We've documented similar situations as being plain changes to
 # standard time, so let's do that here too.  This does not change UTC
 # offsets, only tm_isdst and the time zone abbreviations.  One minor
@@ -486,20 +448,20 @@ Rule	Arg	2008	only	-	Oct	Sun>=15	0:00	1:00	S
 # setting for time stamps past 2038.
 
 # From Paul Eggert (2013-02-21):
-# Milne says Cordoba time was -4:16:48.2.  Round to the nearest second.
+# Milne says Córdoba time was -4:16:48.2.  Round to the nearest second.
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 #
 # Buenos Aires (BA), Capital Federal (CF),
-Zone America/Argentina/Buenos_Aires -3:53:48 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+Zone America/Argentina/Buenos_Aires -3:53:48 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
 			-4:00	Arg	AR%sT	2000 Mar  3
 			-3:00	Arg	AR%sT
 #
-# Cordoba (CB), Santa Fe (SF), Entre Rios (ER), Corrientes (CN), Misiones (MN),
+# Córdoba (CB), Santa Fe (SF), Entre Ríos (ER), Corrientes (CN), Misiones (MN),
 # Chaco (CC), Formosa (FM), Santiago del Estero (SE)
 #
 # Shanks & Pottenger also make the following claims, which we haven't verified:
@@ -519,7 +481,7 @@ Zone America/Argentina/Cordoba -4:16:48 - LMT	1894 Oct 31
 			-4:00	Arg	AR%sT	2000 Mar  3
 			-3:00	Arg	AR%sT
 #
-# Salta (SA), La Pampa (LP), Neuquen (NQ), Rio Negro (RN)
+# Salta (SA), La Pampa (LP), Neuquén (NQ), Rio Negro (RN)
 Zone America/Argentina/Salta -4:21:40 - LMT	1894 Oct 31
 			-4:16:48 -	CMT	1920 May
 			-4:00	-	ART	1930 Dec
@@ -531,7 +493,7 @@ Zone America/Argentina/Salta -4:21:40 - LMT	1894 Oct 31
 			-3:00	Arg	AR%sT	2008 Oct 18
 			-3:00	-	ART
 #
-# Tucuman (TM)
+# Tucumán (TM)
 Zone America/Argentina/Tucuman -4:20:52 - LMT	1894 Oct 31
 			-4:16:48 -	CMT	1920 May
 			-4:00	-	ART	1930 Dec
@@ -642,8 +604,8 @@ Zone America/Argentina/San_Luis -4:25:24 - LMT	1894 Oct 31
 			-3:00	-	ART
 #
 # Santa Cruz (SC)
-Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
@@ -653,9 +615,9 @@ Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
 			-3:00	Arg	AR%sT	2008 Oct 18
 			-3:00	-	ART
 #
-# Tierra del Fuego, Antartida e Islas del Atlantico Sur (TF)
-Zone America/Argentina/Ushuaia -4:33:12 - LMT 1894 Oct 31
-			-4:16:48 -	CMT	1920 May # Cordoba Mean Time
+# Tierra del Fuego, Antártida e Islas del Atlántico Sur (TF)
+Zone America/Argentina/Ushuaia -4:33:12 - LMT	1894 Oct 31
+			-4:16:48 -	CMT	1920 May    # Córdoba Mean Time
 			-4:00	-	ART	1930 Dec
 			-4:00	Arg	AR%sT	1969 Oct  5
 			-3:00	Arg	AR%sT	1999 Oct  3
@@ -686,13 +648,13 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 
 # From IATA SSIM (1996-02):
 # _Only_ the following states in BR1 observe DST: Rio Grande do Sul (RS),
-# Santa Catarina (SC), Parana (PR), Sao Paulo (SP), Rio de Janeiro (RJ),
-# Espirito Santo (ES), Minas Gerais (MG), Bahia (BA), Goias (GO),
+# Santa Catarina (SC), Paraná (PR), São Paulo (SP), Rio de Janeiro (RJ),
+# Espírito Santo (ES), Minas Gerais (MG), Bahia (BA), Goiás (GO),
 # Distrito Federal (DF), Tocantins (TO), Sergipe [SE] and Alagoas [AL].
 # [The last three states are new to this issue of the IATA SSIM.]
 
 # From Gwillim Law (1996-10-07):
-# Geography, history (Tocantins was part of Goias until 1989), and other
+# Geography, history (Tocantins was part of Goiás until 1989), and other
 # sources of time zone information lead me to believe that AL, SE, and TO were
 # always in BR1, and so the only change was whether or not they observed DST....
 # The earliest issue of the SSIM I have is 2/91.  Each issue from then until
@@ -706,16 +668,14 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 # However, some conclusions can be drawn from another IATA manual: the Airline
 # Coding Directory, which lists close to 400 airports in Brazil.  For each
 # airport it gives a time zone which is coded to the SSIM.  From that
-# information, I'm led to conclude that the states of Amapa (AP), Ceara (CE),
-# Maranhao (MA), Paraiba (PR), Pernambuco (PE), Piaui (PI), and Rio Grande do
-# Norte (RN), and the eastern part of Para (PA) are all in BR1 without DST.
+# information, I'm led to conclude that the states of Amapá (AP), Ceará (CE),
+# Maranhão (MA), Paraíba (PR), Pernambuco (PE), Piauí (PI), and Rio Grande do
+# Norte (RN), and the eastern part of Pará (PA) are all in BR1 without DST.
 
 # From Marcos Tadeu (1998-09-27):
-# 
-# Brazilian official page
-# 
+# Brazilian official page 
 
-# From Jesper Norgaard (2000-11-03):
+# From Jesper Nørgaard (2000-11-03):
 # [For an official list of which regions in Brazil use which time zones, see:]
 # http://pcdsh01.on.br/Fusbr.htm
 # http://pcdsh01.on.br/Fusbrhv.htm
@@ -748,13 +708,13 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 
 # From Paul Schulze (2008-06-24):
 # ...by law number 11.662 of April 24, 2008 (published in the "Diario
-# Oficial da Uniao"...) in Brazil there are changes in the timezones,
+# Oficial da União"...) in Brazil there are changes in the timezones,
 # effective today (00:00am at June 24, 2008) as follows:
 #
-# a) The timezone UTC+5 is e[x]tinguished, with all the Acre state and the
+# a) The timezone UTC+5 is extinguished, with all the Acre state and the
 # part of the Amazonas state that had this timezone now being put to the
 # timezone UTC+4
-# b) The whole Para state now is put at timezone UTC+3, instead of just
+# b) The whole Pará state now is put at timezone UTC+3, instead of just
 # part of it, as was before.
 #
 # This change follows a proposal of senator Tiao Viana of Acre state, that
@@ -767,13 +727,11 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 
 # From Rodrigo Severo (2008-06-24):
 # Just correcting the URL:
-# 
 # https://www.in.gov.br/imprensa/visualiza/index.jsp?jornal=do&secao=1&pagina=1&data=25/04/2008
-# 
 #
 # As a result of the above Decree I believe the America/Rio_Branco
 # timezone shall be modified from UTC-5 to UTC-4 and a new timezone shall
-# be created to represent the...west side of the Para State. I
+# be created to represent the...west side of the Pará State. I
 # suggest this new timezone be called Santarem as the most
 # important/populated city in the affected area.
 #
@@ -782,19 +740,16 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 
 # From Alex Krivenyshev (2008-06-24):
 # This is a quick reference page for New and Old Brazil Time Zones map.
-# 
 # http://www.worldtimezone.com/brazil-time-new-old.php
-# 
 #
-# - 4 time zones replaced by 3 time zones-eliminating time zone UTC- 05
-# (state Acre and the part of the Amazonas will be UTC/GMT- 04) - western
-# part of Par state is moving to one timezone UTC- 03 (from UTC -04).
+# - 4 time zones replaced by 3 time zones - eliminating time zone UTC-05
+# (state Acre and the part of the Amazonas will be UTC/GMT-04) - western
+# part of Par state is moving to one timezone UTC-03 (from UTC-04).
 
 # From Paul Eggert (2002-10-10):
 # The official decrees referenced below are mostly taken from
-# 
-# Decretos sobre o Horario de Verao no Brasil
-# .
+# Decretos sobre o Horário de Verão no Brasil.
+# http://pcdsh01.on.br/DecHV.html
 
 # From Steffen Thorsen (2008-08-29):
 # As announced by the government and many newspapers in Brazil late
@@ -806,25 +761,17 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 # It has not yet been posted to http://pcdsh01.on.br/DecHV.html
 #
 # An official page about it:
-# 
 # http://www.mme.gov.br/site/news/detail.do?newsId=16722
-# 
 # Note that this link does not always work directly, but must be accessed
 # by going to
-# 
 # http://www.mme.gov.br/first
-# 
 #
 # One example link that works directly:
-# 
 # http://jornale.com.br/index.php?option=com_content&task=view&id=13530&Itemid=54
 # (Portuguese)
-# 
 #
 # We have a written a short article about it as well:
-# 
 # http://www.timeanddate.com/news/time/brazil-dst-2008-2009.html
-# 
 #
 # From Alexander Krivenyshev (2011-10-04):
 # State Bahia will return to Daylight savings time this year after 8 years off.
@@ -832,17 +779,12 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 # television station in Salvador.
 
 # In Portuguese:
-# 
 # http://g1.globo.com/bahia/noticia/2011/10/governador-jaques-wagner-confirma-horario-de-verao-na-bahia.html
-#  and
-# 
 # http://noticias.terra.com.br/brasil/noticias/0,,OI5390887-EI8139,00-Bahia+volta+a+ter+horario+de+verao+apos+oito+anos.html
-# 
 
 # From Guilherme Bernardes Rodrigues (2011-10-07):
 # There is news in the media, however there is still no decree about it.
-# I just send a e-mail to Zulmira Brandao at
-# http://pcdsh01.on.br/ the
+# I just send a e-mail to Zulmira Brandao at http://pcdsh01.on.br/ the
 # official agency about time in Brazil, and she confirmed that the old rule is
 # still in force.
 
@@ -854,9 +796,7 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 #
 # DECRETO No- 7.584, DE 13 DE OUTUBRO DE 2011
 # Link :
-# 
 # http://www.in.gov.br/visualiza/index.jsp?data=13/10/2011&jornal=1000&pagina=6&totalArquivos=6
-# 
 
 # From Kelley Cook (2012-10-16):
 # The governor of state of Bahia in Brazil announced on Thursday that
@@ -884,42 +824,42 @@ Zone	America/La_Paz	-4:32:36 -	LMT	1890
 # For now, assume western Amazonas will change as well.
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
-# Decree 20,466 (1931-10-01)
-# Decree 21,896 (1932-01-10)
+# Decree 20,466  (1931-10-01)
+# Decree 21,896  (1932-01-10)
 Rule	Brazil	1931	only	-	Oct	 3	11:00	1:00	S
 Rule	Brazil	1932	1933	-	Apr	 1	 0:00	0	-
 Rule	Brazil	1932	only	-	Oct	 3	 0:00	1:00	S
-# Decree 23,195 (1933-10-10)
+# Decree 23,195  (1933-10-10)
 # revoked DST.
-# Decree 27,496 (1949-11-24)
-# Decree 27,998 (1950-04-13)
+# Decree 27,496  (1949-11-24)
+# Decree 27,998  (1950-04-13)
 Rule	Brazil	1949	1952	-	Dec	 1	 0:00	1:00	S
 Rule	Brazil	1950	only	-	Apr	16	 1:00	0	-
 Rule	Brazil	1951	1952	-	Apr	 1	 0:00	0	-
-# Decree 32,308 (1953-02-24)
+# Decree 32,308  (1953-02-24)
 Rule	Brazil	1953	only	-	Mar	 1	 0:00	0	-
-# Decree 34,724 (1953-11-30)
+# Decree 34,724  (1953-11-30)
 # revoked DST.
-# Decree 52,700 (1963-10-18)
+# Decree 52,700  (1963-10-18)
 # established DST from 1963-10-23 00:00 to 1964-02-29 00:00
 # in SP, RJ, GB, MG, ES, due to the prolongation of the drought.
-# Decree 53,071 (1963-12-03)
+# Decree 53,071  (1963-12-03)
 # extended the above decree to all of the national territory on 12-09.
 Rule	Brazil	1963	only	-	Dec	 9	 0:00	1:00	S
-# Decree 53,604 (1964-02-25)
+# Decree 53,604  (1964-02-25)
 # extended summer time by one day to 1964-03-01 00:00 (start of school).
 Rule	Brazil	1964	only	-	Mar	 1	 0:00	0	-
-# Decree 55,639 (1965-01-27)
+# Decree 55,639  (1965-01-27)
 Rule	Brazil	1965	only	-	Jan	31	 0:00	1:00	S
 Rule	Brazil	1965	only	-	Mar	31	 0:00	0	-
-# Decree 57,303 (1965-11-22)
+# Decree 57,303  (1965-11-22)
 Rule	Brazil	1965	only	-	Dec	 1	 0:00	1:00	S
-# Decree 57,843 (1966-02-18)
+# Decree 57,843  (1966-02-18)
 Rule	Brazil	1966	1968	-	Mar	 1	 0:00	0	-
 Rule	Brazil	1966	1967	-	Nov	 1	 0:00	1:00	S
-# Decree 63,429 (1968-10-15)
+# Decree 63,429  (1968-10-15)
 # revoked DST.
-# Decree 91,698 (1985-09-27)
+# Decree 91,698  (1985-09-27)
 Rule	Brazil	1985	only	-	Nov	 2	 0:00	1:00	S
 # Decree 92,310 (1986-01-21)
 # Decree 92,463 (1986-03-13)
@@ -927,42 +867,42 @@ Rule	Brazil	1986	only	-	Mar	15	 0:00	0	-
 # Decree 93,316 (1986-10-01)
 Rule	Brazil	1986	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1987	only	-	Feb	14	 0:00	0	-
-# Decree 94,922 (1987-09-22)
+# Decree 94,922  (1987-09-22)
 Rule	Brazil	1987	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1988	only	-	Feb	 7	 0:00	0	-
-# Decree 96,676 (1988-09-12)
+# Decree 96,676  (1988-09-12)
 # except for the states of AC, AM, PA, RR, RO, and AP (then a territory)
 Rule	Brazil	1988	only	-	Oct	16	 0:00	1:00	S
 Rule	Brazil	1989	only	-	Jan	29	 0:00	0	-
-# Decree 98,077 (1989-08-21)
+# Decree 98,077  (1989-08-21)
 # with the same exceptions
 Rule	Brazil	1989	only	-	Oct	15	 0:00	1:00	S
 Rule	Brazil	1990	only	-	Feb	11	 0:00	0	-
-# Decree 99,530 (1990-09-17)
+# Decree 99,530  (1990-09-17)
 # adopted by RS, SC, PR, SP, RJ, ES, MG, GO, MS, DF.
 # Decree 99,629 (1990-10-19) adds BA, MT.
 Rule	Brazil	1990	only	-	Oct	21	 0:00	1:00	S
 Rule	Brazil	1991	only	-	Feb	17	 0:00	0	-
-# Unnumbered decree (1991-09-25)
+# Unnumbered decree  (1991-09-25)
 # adopted by RS, SC, PR, SP, RJ, ES, MG, BA, GO, MT, MS, DF.
 Rule	Brazil	1991	only	-	Oct	20	 0:00	1:00	S
 Rule	Brazil	1992	only	-	Feb	 9	 0:00	0	-
-# Unnumbered decree (1992-10-16)
+# Unnumbered decree  (1992-10-16)
 # adopted by same states.
 Rule	Brazil	1992	only	-	Oct	25	 0:00	1:00	S
 Rule	Brazil	1993	only	-	Jan	31	 0:00	0	-
-# Decree 942 (1993-09-28)
+# Decree 942  (1993-09-28)
 # adopted by same states, plus AM.
-# Decree 1,252 (1994-09-22;
+# Decree 1,252  (1994-09-22;
 # web page corrected 2004-01-07) adopted by same states, minus AM.
-# Decree 1,636 (1995-09-14)
+# Decree 1,636  (1995-09-14)
 # adopted by same states, plus MT and TO.
-# Decree 1,674 (1995-10-13)
+# Decree 1,674  (1995-10-13)
 # adds AL, SE.
 Rule	Brazil	1993	1995	-	Oct	Sun>=11	 0:00	1:00	S
 Rule	Brazil	1994	1995	-	Feb	Sun>=15	 0:00	0	-
 Rule	Brazil	1996	only	-	Feb	11	 0:00	0	-
-# Decree 2,000 (1996-09-04)
+# Decree 2,000  (1996-09-04)
 # adopted by same states, minus AL, SE.
 Rule	Brazil	1996	only	-	Oct	 6	 0:00	1:00	S
 Rule	Brazil	1997	only	-	Feb	16	 0:00	0	-
@@ -975,53 +915,51 @@ Rule	Brazil	1997	only	-	Feb	16	 0:00	0	-
 #
 # Decree 2,317 (1997-09-04), adopted by same states.
 Rule	Brazil	1997	only	-	Oct	 6	 0:00	1:00	S
-# Decree 2,495
+# Decree 2,495 
 # (1998-02-10)
 Rule	Brazil	1998	only	-	Mar	 1	 0:00	0	-
-# Decree 2,780 (1998-09-11)
+# Decree 2,780  (1998-09-11)
 # adopted by the same states as before.
 Rule	Brazil	1998	only	-	Oct	11	 0:00	1:00	S
 Rule	Brazil	1999	only	-	Feb	21	 0:00	0	-
-# Decree 3,150
+# Decree 3,150 
 # (1999-08-23) adopted by same states.
-# Decree 3,188 (1999-09-30)
+# Decree 3,188  (1999-09-30)
 # adds SE, AL, PB, PE, RN, CE, PI, MA and RR.
 Rule	Brazil	1999	only	-	Oct	 3	 0:00	1:00	S
 Rule	Brazil	2000	only	-	Feb	27	 0:00	0	-
-# Decree 3,592 (2000-09-06)
+# Decree 3,592  (2000-09-06)
 # adopted by the same states as before.
-# Decree 3,630 (2000-10-13)
+# Decree 3,630  (2000-10-13)
 # repeals DST in PE and RR, effective 2000-10-15 00:00.
-# Decree 3,632 (2000-10-17)
+# Decree 3,632  (2000-10-17)
 # repeals DST in SE, AL, PB, RN, CE, PI and MA, effective 2000-10-22 00:00.
-# Decree 3,916
+# Decree 3,916 
 # (2001-09-13) reestablishes DST in AL, CE, MA, PB, PE, PI, RN, SE.
 Rule	Brazil	2000	2001	-	Oct	Sun>=8	 0:00	1:00	S
 Rule	Brazil	2001	2006	-	Feb	Sun>=15	 0:00	0	-
 # Decree 4,399 (2002-10-01) repeals DST in AL, CE, MA, PB, PE, PI, RN, SE.
-# 4,399
+# 4,399 
 Rule	Brazil	2002	only	-	Nov	 3	 0:00	1:00	S
 # Decree 4,844 (2003-09-24; corrected 2003-09-26) repeals DST in BA, MT, TO.
-# 4,844
+# 4,844 
 Rule	Brazil	2003	only	-	Oct	19	 0:00	1:00	S
 # Decree 5,223 (2004-10-01) reestablishes DST in MT.
-# 5,223
+# 5,223 
 Rule	Brazil	2004	only	-	Nov	 2	 0:00	1:00	S
-# Decree 5,539 (2005-09-19),
+# Decree 5,539  (2005-09-19),
 # adopted by the same states as before.
 Rule	Brazil	2005	only	-	Oct	16	 0:00	1:00	S
-# Decree 5,920 (2006-10-03),
+# Decree 5,920  (2006-10-03),
 # adopted by the same states as before.
 Rule	Brazil	2006	only	-	Nov	 5	 0:00	1:00	S
 Rule	Brazil	2007	only	-	Feb	25	 0:00	0	-
-# Decree 6,212 (2007-09-26),
+# Decree 6,212  (2007-09-26),
 # adopted by the same states as before.
 Rule	Brazil	2007	only	-	Oct	Sun>=8	 0:00	1:00	S
 # From Frederico A. C. Neves (2008-09-10):
 # According to this decree
-# 
 # http://www.planalto.gov.br/ccivil_03/_Ato2007-2010/2008/Decreto/D6558.htm
-# 
 # [t]he DST period in Brazil now on will be from the 3rd Oct Sunday to the
 # 3rd Feb Sunday. There is an exception on the return date when this is
 # the Carnival Sunday then the return date will be the next Sunday...
@@ -1056,29 +994,29 @@ Zone America/Noronha	-2:09:40 -	LMT	1914
 			-2:00	Brazil	FN%sT	2002 Oct  1
 			-2:00	-	FNT
 # Other Atlantic islands have no permanent settlement.
-# These include Trindade and Martin Vaz (administratively part of ES),
-# Atol das Rocas (RN), and Penedos de Sao Pedro e Sao Paulo (PE).
+# These include Trindade and Martim Vaz (administratively part of ES),
+# Rocas Atoll (RN), and the St Peter and St Paul Archipelago (PE).
 # Fernando de Noronha was a separate territory from 1942-09-02 to 1989-01-01;
 # it also included the Penedos.
 #
-# Amapa (AP), east Para (PA)
-# East Para includes Belem, Maraba, Serra Norte, and Sao Felix do Xingu.
-# The division between east and west Para is the river Xingu.
+# Amapá (AP), east Pará (PA)
+# East Pará includes Belém, Marabá, Serra Norte, and São Félix do Xingu.
+# The division between east and west Pará is the river Xingu.
 # In the north a very small part from the river Javary (now Jari I guess,
-# the border with Amapa) to the Amazon, then to the Xingu.
+# the border with Amapá) to the Amazon, then to the Xingu.
 Zone America/Belem	-3:13:56 -	LMT	1914
 			-3:00	Brazil	BR%sT	1988 Sep 12
 			-3:00	-	BRT
 #
-# west Para (PA)
-# West Para includes Altamira, Oribidos, Prainha, Oriximina, and Santarem.
+# west Pará (PA)
+# West Pará includes Altamira, Óbidos, Prainha, Oriximiná, and Santarém.
 Zone America/Santarem	-3:38:48 -	LMT	1914
 			-4:00	Brazil	AM%sT	1988 Sep 12
-			-4:00	-	AMT	2008 Jun 24 00:00
+			-4:00	-	AMT	2008 Jun 24  0:00
 			-3:00	-	BRT
 #
-# Maranhao (MA), Piaui (PI), Ceara (CE), Rio Grande do Norte (RN),
-# Paraiba (PB)
+# Maranhão (MA), Piauí (PI), Ceará (CE), Rio Grande do Norte (RN),
+# Paraíba (PB)
 Zone America/Fortaleza	-2:34:00 -	LMT	1914
 			-3:00	Brazil	BR%sT	1990 Sep 17
 			-3:00	-	BRT	1999 Sep 30
@@ -1125,11 +1063,11 @@ Zone America/Bahia	-2:34:04 -	LMT	1914
 			-3:00	Brazil	BR%sT	2012 Oct 21
 			-3:00	-	BRT
 #
-# Goias (GO), Distrito Federal (DF), Minas Gerais (MG),
-# Espirito Santo (ES), Rio de Janeiro (RJ), Sao Paulo (SP), Parana (PR),
+# Goiás (GO), Distrito Federal (DF), Minas Gerais (MG),
+# Espírito Santo (ES), Rio de Janeiro (RJ), São Paulo (SP), Paraná (PR),
 # Santa Catarina (SC), Rio Grande do Sul (RS)
 Zone America/Sao_Paulo	-3:06:28 -	LMT	1914
-			-3:00	Brazil	BR%sT	1963 Oct 23 00:00
+			-3:00	Brazil	BR%sT	1963 Oct 23  0:00
 			-3:00	1:00	BRST	1964
 			-3:00	Brazil	BR%sT
 #
@@ -1143,7 +1081,7 @@ Zone America/Cuiaba	-3:44:20 -	LMT	1914
 			-4:00	-	AMT	2004 Oct  1
 			-4:00	Brazil	AM%sT
 #
-# Rondonia (RO)
+# Rondônia (RO)
 Zone America/Porto_Velho -4:15:36 -	LMT	1914
 			-4:00	Brazil	AM%sT	1988 Sep 12
 			-4:00	-	AMT
@@ -1155,7 +1093,7 @@ Zone America/Boa_Vista	-4:02:40 -	LMT	1914
 			-4:00	Brazil	AM%sT	2000 Oct 15
 			-4:00	-	AMT
 #
-# east Amazonas (AM): Boca do Acre, Jutai, Manaus, Floriano Peixoto
+# east Amazonas (AM): Boca do Acre, Jutaí, Manaus, Floriano Peixoto
 # The great circle line from Tabatinga to Porto Acre divides
 # east from west Amazonas.
 Zone America/Manaus	-4:00:04 -	LMT	1914
@@ -1165,19 +1103,19 @@ Zone America/Manaus	-4:00:04 -	LMT	1914
 			-4:00	-	AMT
 #
 # west Amazonas (AM): Atalaia do Norte, Boca do Maoco, Benjamin Constant,
-#	Eirunepe, Envira, Ipixuna
+#	Eirunepé, Envira, Ipixuna
 Zone America/Eirunepe	-4:39:28 -	LMT	1914
 			-5:00	Brazil	AC%sT	1988 Sep 12
 			-5:00	-	ACT	1993 Sep 28
 			-5:00	Brazil	AC%sT	1994 Sep 22
-			-5:00	-	ACT	2008 Jun 24 00:00
+			-5:00	-	ACT	2008 Jun 24  0:00
 			-4:00	-	AMT	2013 Nov 10
 			-5:00	-	ACT
 #
 # Acre (AC)
 Zone America/Rio_Branco	-4:31:12 -	LMT	1914
 			-5:00	Brazil	AC%sT	1988 Sep 12
-			-5:00	-	ACT	2008 Jun 24 00:00
+			-5:00	-	ACT	2008 Jun 24  0:00
 			-4:00	-	AMT	2013 Nov 10
 			-5:00	-	ACT
 
@@ -1198,66 +1136,54 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1914
 # From Oscar van Vlijmen (2006-10-08):
 # http://www.horaoficial.cl/cambio.htm
 
-# From Jesper Norgaard Welen (2006-10-08):
+# From Jesper Nørgaard Welen (2006-10-08):
 # I think that there are some obvious mistakes in the suggested link
 # from Oscar van Vlijmen,... for instance entry 66 says that GMT-4
 # ended 1990-09-12 while entry 67 only begins GMT-3 at 1990-09-15
 # (they should have been 1990-09-15 and 1990-09-16 respectively), but
 # anyhow it clears up some doubts too.
 
-# From Paul Eggert (2006-12-27):
-# The following data for Chile and America/Santiago are from
+# From Paul Eggert (2014-08-12):
+# The following data entries for Chile and America/Santiago are from
 #  (2006-09-20), transcribed by
-# Jesper Norgaard Welen.  The data for Pacific/Easter are from Shanks
+# Jesper Nørgaard Welen.  The data entries for Pacific/Easter are from Shanks
 # & Pottenger, except with DST transitions after 1932 cloned from
-# America/Santiago.  The pre-1980 Pacific/Easter data are dubious,
+# America/Santiago.  The pre-1980 Pacific/Easter data entries are dubious,
 # but we have no other source.
 
-# From German Poo-Caaman~o (2008-03-03):
+# From Germán Poo-Caamaño (2008-03-03):
 # Due to drought, Chile extends Daylight Time in three weeks.  This
 # is one-time change (Saturday 3/29 at 24:00 for America/Santiago
 # and Saturday 3/29 at 22:00 for Pacific/Easter)
 # The Supreme Decree is located at
-# 
 # http://www.shoa.cl/servicios/supremo316.pdf
-# 
 # and the instructions for 2008 are located in:
-# 
 # http://www.horaoficial.cl/cambio.htm
-# .
 
-# From Jose Miguel Garrido (2008-03-05):
+# From José Miguel Garrido (2008-03-05):
 # ...
 # You could see the announces of the change on
-# 
 # http://www.shoa.cl/noticias/2008/04hora/hora.htm
-# .
 
 # From Angel Chiang (2010-03-04):
 # Subject: DST in Chile exceptionally extended to 3 April due to earthquake
-# 
 # http://www.gobiernodechile.cl/viewNoticia.aspx?idArticulo=30098
-# 
 # (in Spanish, last paragraph).
 #
 # This is breaking news. There should be more information available later.
 
-# From Arthur Daivd Olson (2010-03-06):
+# From Arthur David Olson (2010-03-06):
 # Angel Chiang's message confirmed by Julio Pacheco; Julio provided a patch.
 
-# From Glenn Eychaner (2011-03-02): [geychaner@mac.com]
+# From Glenn Eychaner (2011-03-02):
 # It appears that the Chilean government has decided to postpone the
 # change from summer time to winter time again, by three weeks to April
 # 2nd:
-# 
 # http://www.emol.com/noticias/nacional/detalle/detallenoticias.asp?idnoticia=467651
-# 
 #
 # This is not yet reflected in the official "cambio de hora" site, but
 # probably will be soon:
-# 
 # http://www.horaoficial.cl/cambio.htm
-# 
 
 # From Arthur David Olson (2011-03-02):
 # The emol.com article mentions a water shortage as the cause of the
@@ -1265,9 +1191,7 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1914
 
 # From Glenn Eychaner (2011-03-28):
 # The article:
-# 
 # http://diario.elmercurio.com/2011/03/28/_portada/_portada/noticias/7565897A-CA86-49E6-9E03-660B21A4883E.htm?id=3D{7565897A-CA86-49E6-9E03-660B21A4883E}
-# 
 #
 # In English:
 # Chile's clocks will go back an hour this year on the 7th of May instead
@@ -1298,7 +1222,7 @@ Zone America/Rio_Branco	-4:31:12 -	LMT	1914
 # start date is 2013-09-08 00:00....
 # http://www.gob.cl/informa/2013/02/15/gobierno-anuncia-fechas-de-cambio-de-hora-para-el-ano-2013.htm
 
-# From Jose Miguel Garrido (2014-02-19):
+# From José Miguel Garrido (2014-02-19):
 # Today appeared in the Diario Oficial a decree amending the time change
 # dates to 2014.
 # DST End: last Saturday of April 2014 (Sun 27 Apr 2014 03:00 UTC)
@@ -1352,7 +1276,7 @@ Rule	Chile	2012	max	-	Sep	Sun>=2	4:00u	1:00	S
 # (1996-09) says 1998-03-08.  Ignore these.
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Santiago	-4:42:46 -	LMT	1890
-			-4:42:46 -	SMT	1910 	    # Santiago Mean Time
+			-4:42:46 -	SMT	1910        # Santiago Mean Time
 			-5:00	-	CLT	1916 Jul  1 # Chile Time
 			-4:42:46 -	SMT	1918 Sep  1 # Santiago Mean Time
 			-4:00	-	CLT	1919 Jul  1 # Chile Time
@@ -1361,16 +1285,16 @@ Zone America/Santiago	-4:42:46 -	LMT	1890
 			-4:00	Chile	CL%sT
 Zone Pacific/Easter	-7:17:44 -	LMT	1890
 			-7:17:28 -	EMT	1932 Sep    # Easter Mean Time
-			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter I Time
+			-7:00	Chile	EAS%sT	1982 Mar 13 21:00 # Easter Time
 			-6:00	Chile	EAS%sT
 #
-# Sala y Gomez Island is like Pacific/Easter.
-# Other Chilean locations, including Juan Fernandez Is, San Ambrosio,
-# San Felix, and Antarctic bases, are like America/Santiago.
+# Salas y Gómez Island is uninhabited.
+# Other Chilean locations, including Juan Fernández Is, Desventuradas Is,
+# and Antarctic bases, are like America/Santiago.
 
 # Colombia
 
-# Milne gives 4:56:16.4 for Bogota time in 1899; round to nearest.  He writes,
+# Milne gives 4:56:16.4 for Bogotá time in 1899; round to nearest.  He writes,
 # "A variation of fifteen minutes in the public clocks of Bogota is not rare."
 
 # Rule	NAME	FROM	TO	TYPE	IN	ON	AT	SAVE	LETTER/S
@@ -1378,37 +1302,37 @@ Rule	CO	1992	only	-	May	 3	0:00	1:00	S
 Rule	CO	1993	only	-	Apr	 4	0:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Bogota	-4:56:16 -	LMT	1884 Mar 13
-			-4:56:16 -	BMT	1914 Nov 23 # Bogota Mean Time
+			-4:56:16 -	BMT	1914 Nov 23 # Bogotá Mean Time
 			-5:00	CO	CO%sT	# Colombia Time
 # Malpelo, Providencia, San Andres
 # no information; probably like America/Bogota
 
-# Curacao
+# Curaçao
 
-# Milne gives 4:35:46.9 for Curacao mean time; round to nearest.
+# Milne gives 4:35:46.9 for Curaçao mean time; round to nearest.
 #
 # From Paul Eggert (2006-03-22):
 # Shanks & Pottenger say that The Bottom and Philipsburg have been at
 # -4:00 since standard time was introduced on 1912-03-02; and that
 # Kralendijk and Rincon used Kralendijk Mean Time (-4:33:08) from
 # 1912-02-02 to 1965-01-01.  The former is dubious, since S&P also say
-# Saba Island has been like Curacao.
+# Saba Island has been like Curaçao.
 # This all predates our 1970 cutoff, though.
 #
-# By July 2007 Curacao and St Maarten are planned to become
+# By July 2007 Curaçao and St Maarten are planned to become
 # associated states within the Netherlands, much like Aruba;
 # Bonaire, Saba and St Eustatius would become directly part of the
 # Netherlands as Kingdom Islands.  This won't affect their time zones
 # though, as far as we know.
 #
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12	# Willemstad
+Zone	America/Curacao	-4:35:47 -	LMT	1912 Feb 12 # Willemstad
 			-4:30	-	ANT	1965 # Netherlands Antilles Time
 			-4:00	-	AST
 
 # From Arthur David Olson (2011-06-15):
 # use links for places with new iso3166 codes.
-# The name "Lower Prince's Quarter" is both longer than fourteen charaters
+# The name "Lower Prince's Quarter" is both longer than fourteen characters
 # and contains an apostrophe; use "Lower_Princes" below.
 
 Link	America/Curacao	America/Lower_Princes	# Sint Maarten
@@ -1416,7 +1340,7 @@ Link	America/Curacao	America/Kralendijk	# Caribbean Netherlands
 
 # Ecuador
 #
-# Milne says the Sentral and South American Telegraph Company used -5:24:15.
+# Milne says the Central and South American Telegraph Company used -5:24:15.
 #
 # From Paul Eggert (2007-03-04):
 # Apparently Ecuador had a failed experiment with DST in 1992.
@@ -1427,10 +1351,10 @@ Link	America/Curacao	America/Kralendijk	# Caribbean Netherlands
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Guayaquil	-5:19:20 -	LMT	1890
 			-5:14:00 -	QMT	1931 # Quito Mean Time
-			-5:00	-	ECT	     # Ecuador Time
+			-5:00	-	ECT	# Ecuador Time
 Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
 			-5:00	-	ECT	1986
-			-6:00	-	GALT	     # Galapagos Time
+			-6:00	-	GALT	# Galápagos Time
 
 # Falklands
 
@@ -1439,7 +1363,7 @@ Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
 # the IATA gives 1996-09-08.  Go with Shanks & Pottenger.
 
 # From Falkland Islands Government Office, London (2001-01-22)
-# via Jesper Norgaard:
+# via Jesper Nørgaard:
 # ... the clocks revert back to Local Mean Time at 2 am on Sunday 15
 # April 2001 and advance one hour to summer time at 2 am on Sunday 2
 # September.  It is anticipated that the clocks will revert back at 2
@@ -1488,9 +1412,7 @@ Zone Pacific/Galapagos	-5:58:24 -	LMT	1931 # Puerto Baquerizo Moreno
 # daylight saving time.
 #
 # One source:
-# 
 # http://www.falklandnews.com/public/story.cfm?get=5914&source=3
-# 
 #
 # We have gotten this confirmed by a clerk of the legislative assembly:
 # Normally the clocks revert to Local Mean Time (UTC/GMT -4 hours) on the
@@ -1531,10 +1453,10 @@ Rule	Falk	2001	2010	-	Apr	Sun>=15	2:00	0	-
 Rule	Falk	2001	2010	-	Sep	Sun>=1	2:00	1:00	S
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone Atlantic/Stanley	-3:51:24 -	LMT	1890
-			-3:51:24 -	SMT	1912 Mar 12  # Stanley Mean Time
-			-4:00	Falk	FK%sT	1983 May     # Falkland Is Time
+			-3:51:24 -	SMT	1912 Mar 12 # Stanley Mean Time
+			-4:00	Falk	FK%sT	1983 May    # Falkland Is Time
 			-3:00	Falk	FK%sT	1985 Sep 15
-			-4:00	Falk	FK%sT	2010 Sep 5 02:00
+			-4:00	Falk	FK%sT	2010 Sep  5  2:00
 			-3:00	-	FKST
 
 # French Guiana
@@ -1545,7 +1467,7 @@ Zone America/Cayenne	-3:29:20 -	LMT	1911 Jul
 
 # Guyana
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar	# Georgetown
+Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar    # Georgetown
 			-3:45	-	GBGT	1966 May 26 # Br Guiana Time
 			-3:45	-	GYT	1975 Jul 31 # Guyana Time
 			-3:00	-	GYT	1991
@@ -1555,8 +1477,8 @@ Zone	America/Guyana	-3:52:40 -	LMT	1915 Mar	# Georgetown
 # Paraguay
 #
 # From Paul Eggert (2006-03-22):
-# Shanks & Pottenger say that spring transitions are from 01:00 -> 02:00,
-# and autumn transitions are from 00:00 -> 23:00.  Go with pre-1999
+# Shanks & Pottenger say that spring transitions are 01:00 -> 02:00,
+# and autumn transitions are 00:00 -> 23:00.  Go with pre-1999
 # editions of Shanks, and with the IATA, who say transitions occur at 00:00.
 #
 # From Waldemar Villamayor-Venialbo (2013-09-20):
@@ -1582,9 +1504,8 @@ Rule	Para	1996	only	-	Mar	 1	0:00	0	-
 # (10-01).
 #
 # Translated by Gwillim Law (2001-02-27) from
-# 
-# Noticias, a daily paper in Asuncion, Paraguay (2000-10-01)
-# :
+# Noticias, a daily paper in Asunción, Paraguay (2000-10-01):
+# http://www.diarionoticias.com.py/011000/nacional/naciona1.htm
 # Starting at 0:00 today, the clock will be set forward 60 minutes, in
 # fulfillment of Decree No. 7,273 of the Executive Power....  The time change
 # system has been operating for several years.  Formerly there was a separate
@@ -1605,21 +1526,18 @@ Rule	Para	1998	2001	-	Mar	Sun>=1	0:00	0	-
 Rule	Para	2002	2004	-	Apr	Sun>=1	0:00	0	-
 Rule	Para	2002	2003	-	Sep	Sun>=1	0:00	1:00	S
 #
-# From Jesper Norgaard Welen (2005-01-02):
+# From Jesper Nørgaard Welen (2005-01-02):
 # There are several sources that claim that Paraguay made
 # a timezone rule change in autumn 2004.
 # From Steffen Thorsen (2005-01-05):
 # Decree 1,867 (2004-03-05)
-# From Carlos Raul Perasso via Jesper Norgaard Welen (2006-10-13)
-# 
+# From Carlos Raúl Perasso via Jesper Nørgaard Welen (2006-10-13)
+# http://www.presidencia.gov.py/decretos/D1867.pdf
 Rule	Para	2004	2009	-	Oct	Sun>=15	0:00	1:00	S
 Rule	Para	2005	2009	-	Mar	Sun>=8	0:00	0	-
-# From Carlos Raul Perasso (2010-02-18):
-# By decree number 3958 issued yesterday (
-# 
+# From Carlos Raúl Perasso (2010-02-18):
+# By decree number 3958 issued yesterday
 # http://www.presidencia.gov.py/v1/wp-content/uploads/2010/02/decreto3958.pdf
-# 
-# )
 # Paraguay changes its DST schedule, postponing the March rule to April and
 # modifying the October date. The decree reads:
 # ...
@@ -1635,25 +1553,25 @@ Rule	Para	2010	2012	-	Apr	Sun>=8	0:00	0	-
 # Paraguay will end DST on 2013-03-24 00:00....
 # http://www.ande.gov.py/interna.php?id=1075
 #
-# From Carlos Raul Perasso (2013-03-15):
+# From Carlos Raúl Perasso (2013-03-15):
 # The change in Paraguay is now final.  Decree number 10780
 # http://www.presidencia.gov.py/uploads/pdf/presidencia-3b86ff4b691c79d4f5927ca964922ec74772ce857c02ca054a52a37b49afc7fb.pdf
-# From Carlos Raul Perasso (2014-02-28):
+# From Carlos Raúl Perasso (2014-02-28):
 # Decree 1264 can be found at:
 # http://www.presidencia.gov.py/archivos/documentos/DECRETO1264_ey9r8zai.pdf
 Rule	Para	2013	max	-	Mar	Sun>=22	0:00	0	-
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Asuncion	-3:50:40 -	LMT	1890
-			-3:50:40 -	AMT	1931 Oct 10 # Asuncion Mean Time
-			-4:00	-	PYT	1972 Oct # Paraguay Time
+			-3:50:40 -	AMT	1931 Oct 10 # Asunción Mean Time
+			-4:00	-	PYT	1972 Oct    # Paraguay Time
 			-3:00	-	PYT	1974 Apr
 			-4:00	Para	PY%sT
 
 # Peru
 #
-# 
-# From Evelyn C. Leeper via Mark Brader (2003-10-26):
+# From Evelyn C. Leeper via Mark Brader (2003-10-26)
+# :
 # When we were in Peru in 1985-1986, they apparently switched over
 # sometime between December 29 and January 3 while we were on the Amazon.
 #
@@ -1679,7 +1597,7 @@ Zone	America/Lima	-5:08:12 -	LMT	1890
 
 # South Georgia
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
-Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890		# Grytviken
+Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890 # Grytviken
 			-2:00	-	GST	# South Georgia Time
 
 # South Sandwich Is
@@ -1689,9 +1607,9 @@ Zone Atlantic/South_Georgia -2:26:08 -	LMT	1890		# Grytviken
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Paramaribo	-3:40:40 -	LMT	1911
 			-3:40:52 -	PMT	1935     # Paramaribo Mean Time
-			-3:40:36 -	PMT	1945 Oct # The capital moved?
+			-3:40:36 -	PMT	1945 Oct    # The capital moved?
 			-3:30	-	NEGT	1975 Nov 20 # Dutch Guiana Time
-			-3:30	-	SRT	1984 Oct # Suriname Time
+			-3:30	-	SRT	1984 Oct    # Suriname Time
 			-3:00	-	SRT
 
 # Trinidad and Tobago
@@ -1706,7 +1624,7 @@ Link America/Port_of_Spain America/Grenada
 Link America/Port_of_Spain America/Guadeloupe
 Link America/Port_of_Spain America/Marigot	# St Martin (French part)
 Link America/Port_of_Spain America/Montserrat
-Link America/Port_of_Spain America/St_Barthelemy
+Link America/Port_of_Spain America/St_Barthelemy # St Barthélemy
 Link America/Port_of_Spain America/St_Kitts	# St Kitts & Nevis
 Link America/Port_of_Spain America/St_Lucia
 Link America/Port_of_Spain America/St_Thomas	# Virgin Islands (US)
@@ -1765,7 +1683,7 @@ Rule	Uruguay	1990	1991	-	Oct	Sun>=21	 0:00	1:00	S
 Rule	Uruguay	1992	only	-	Oct	18	 0:00	1:00	S
 Rule	Uruguay	1993	only	-	Feb	28	 0:00	0	-
 # From Eduardo Cota (2004-09-20):
-# The uruguayan government has decreed a change in the local time....
+# The Uruguayan government has decreed a change in the local time....
 # http://www.presidencia.gub.uy/decretos/2004091502.htm
 Rule	Uruguay	2004	only	-	Sep	19	 0:00	1:00	S
 # From Steffen Thorsen (2005-03-11):
@@ -1779,14 +1697,14 @@ Rule	Uruguay	2005	only	-	Mar	27	 2:00	0	-
 # 02:00 local time, official time in Uruguay will be at GMT -2.
 Rule	Uruguay	2005	only	-	Oct	 9	 2:00	1:00	S
 Rule	Uruguay	2006	only	-	Mar	12	 2:00	0	-
-# From Jesper Norgaard Welen (2006-09-06):
+# From Jesper Nørgaard Welen (2006-09-06):
 # http://www.presidencia.gub.uy/_web/decretos/2006/09/CM%20210_08%2006%202006_00001.PDF
 Rule	Uruguay	2006	max	-	Oct	Sun>=1	 2:00	1:00	S
 Rule	Uruguay	2007	max	-	Mar	Sun>=8	 2:00	0	-
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone America/Montevideo	-3:44:44 -	LMT	1898 Jun 28
-			-3:44:44 -	MMT	1920 May  1	# Montevideo MT
-			-3:30	Uruguay	UY%sT	1942 Dec 14	# Uruguay Time
+			-3:44:44 -	MMT	1920 May  1 # Montevideo MT
+			-3:30	Uruguay	UY%sT	1942 Dec 14 # Uruguay Time
 			-3:00	Uruguay	UY%sT
 
 # Venezuela
@@ -1794,14 +1712,14 @@ Zone America/Montevideo	-3:44:44 -	LMT	1898 Jun 28
 # From John Stainforth (2007-11-28):
 # ... the change for Venezuela originally expected for 2007-12-31 has
 # been brought forward to 2007-12-09.  The official announcement was
-# published today in the "Gaceta Oficial de la Republica Bolivariana
-# de Venezuela, numero 38.819" (official document for all laws or
+# published today in the "Gaceta Oficial de la República Bolivariana
+# de Venezuela, número 38.819" (official document for all laws or
 # resolution publication)
 # http://www.globovision.com/news.php?nid=72208
 
 # Zone	NAME		GMTOFF	RULES	FORMAT	[UNTIL]
 Zone	America/Caracas	-4:27:44 -	LMT	1890
 			-4:27:40 -	CMT	1912 Feb 12 # Caracas Mean Time?
-			-4:30	-	VET	1965	     # Venezuela Time
-			-4:00	-	VET	2007 Dec  9 03:00
+			-4:30	-	VET	1965        # Venezuela Time
+			-4:00	-	VET	2007 Dec  9  3:00
 			-4:30	-	VET
diff --git a/jdk/make/data/tzdata/systemv b/jdk/make/data/tzdata/systemv
index f909f9c76db..c7b9a888e88 100644
--- a/jdk/make/data/tzdata/systemv
+++ b/jdk/make/data/tzdata/systemv
@@ -21,7 +21,6 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# 
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 
diff --git a/jdk/make/data/tzdata/zone.tab b/jdk/make/data/tzdata/zone.tab
index 7cec627fd95..45351ca8486 100644
--- a/jdk/make/data/tzdata/zone.tab
+++ b/jdk/make/data/tzdata/zone.tab
@@ -21,39 +21,27 @@
 # or visit www.oracle.com if you need additional information or have any
 # questions.
 #
-# TZ zone descriptions
+# tz zone descriptions (deprecated version)
 #
 # This file is in the public domain, so clarified as of
 # 2009-05-17 by Arthur David Olson.
 #
-# From Paul Eggert (2013-08-14):
+# From Paul Eggert (2014-07-31):
+# This file is intended as a backward-compatibility aid for older programs.
+# New programs should use zone1970.tab.  This file is like zone1970.tab (see
+# zone1970.tab's comments), but with the following additional restrictions:
 #
-# This file contains a table where each row stands for an area that is
-# the intersection of a region identified by a country code and of a
-# zone where civil clocks have agreed since 1970.  The columns of the
-# table are as follows:
+# 1.  This file contains only ASCII characters.
+# 2.  The first data column contains exactly one country code.
 #
-# 1.  ISO 3166 2-character country code.  See the file 'iso3166.tab'.
-# 2.  Latitude and longitude of the area's principal location
-#     in ISO 6709 sign-degrees-minutes-seconds format,
-#     either +-DDMM+-DDDMM or +-DDMMSS+-DDDMMSS,
-#     first latitude (+ is north), then longitude (+ is east).
-# 3.  Zone name used in value of TZ environment variable.
-#     Please see the 'Theory' file for how zone names are chosen.
-#     If multiple zones overlap a country, each has a row in the
-#     table, with column 1 being duplicated.
-# 4.  Comments; present if and only if the country has multiple rows.
-#
-# Columns are separated by a single tab.
-# The table is sorted first by country, then an order within the country that
-# (1) makes some geographical sense, and
-# (2) puts the most populous areas first, where that does not contradict (1).
-#
-# Lines beginning with '#' are comments.
+# Because of (2), each row stands for an area that is the intersection
+# of a region identified by a country code and of a zone where civil
+# clocks have agreed since 1970; this is a narrower definition than
+# that of zone1970.tab.
 #
 # This table is intended as an aid for users, to help them select time
-# zone data appropriate for their practical needs.  It is not intended
-# to take or endorse any position on legal or territorial claims.
+# zone data entries appropriate for their practical needs.  It is not
+# intended to take or endorse any position on legal or territorial claims.
 #
 #country-
 #code	coordinates	TZ			comments
@@ -72,7 +60,7 @@ AQ	-6736+06253	Antarctica/Mawson	Mawson Station, Holme Bay
 AQ	-6835+07758	Antarctica/Davis	Davis Station, Vestfold Hills
 AQ	-6617+11031	Antarctica/Casey	Casey Station, Bailey Peninsula
 AQ	-7824+10654	Antarctica/Vostok	Vostok Station, Lake Vostok
-AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Terre Adelie
+AQ	-6640+14001	Antarctica/DumontDUrville	Dumont-d'Urville Station, Adelie Land
 AQ	-690022+0393524	Antarctica/Syowa	Syowa Station, E Ongul I
 AQ	-720041+0023206	Antarctica/Troll	Troll Station, Queen Maud Land
 AR	-3436-05827	America/Argentina/Buenos_Aires	Buenos Aires (BA, CF)
@@ -151,7 +139,7 @@ CA	+4901-08816	America/Nipigon	Eastern Time - Ontario & Quebec - places that did
 CA	+4823-08915	America/Thunder_Bay	Eastern Time - Thunder Bay, Ontario
 CA	+6344-06828	America/Iqaluit	Eastern Time - east Nunavut - most locations
 CA	+6608-06544	America/Pangnirtung	Eastern Time - Pangnirtung, Nunavut
-CA	+744144-0944945	America/Resolute	Central Standard Time - Resolute, Nunavut
+CA	+744144-0944945	America/Resolute	Central Time - Resolute, Nunavut
 CA	+484531-0913718	America/Atikokan	Eastern Standard Time - Atikokan, Ontario and Southampton I, Nunavut
 CA	+624900-0920459	America/Rankin_Inlet	Central Time - central Nunavut
 CA	+4953-09709	America/Winnipeg	Central Time - Manitoba & west Ontario
@@ -176,13 +164,10 @@ CH	+4723+00832	Europe/Zurich
 CI	+0519-00402	Africa/Abidjan
 CK	-2114-15946	Pacific/Rarotonga
 CL	-3327-07040	America/Santiago	most locations
-CL	-2709-10926	Pacific/Easter	Easter Island & Sala y Gomez
+CL	-2709-10926	Pacific/Easter	Easter Island
 CM	+0403+00942	Africa/Douala
-CN	+3114+12128	Asia/Shanghai	east China - Beijing, Guangdong, Shanghai, etc.
-CN	+4545+12641	Asia/Harbin	Heilongjiang (except Mohe), Jilin
-CN	+2934+10635	Asia/Chongqing	central China - Sichuan, Yunnan, Guangxi, Shaanxi, Guizhou, etc.
-CN	+4348+08735	Asia/Urumqi	most of Tibet & Xinjiang
-CN	+3929+07559	Asia/Kashgar	west Tibet & Xinjiang
+CN	+3114+12128	Asia/Shanghai	Beijing Time
+CN	+4348+08735	Asia/Urumqi	Xinjiang Time
 CO	+0436-07405	America/Bogota
 CR	+0956-08405	America/Costa_Rica
 CU	+2308-08222	America/Havana
@@ -364,24 +349,26 @@ RE	-2052+05528	Indian/Reunion
 RO	+4426+02606	Europe/Bucharest
 RS	+4450+02030	Europe/Belgrade
 RU	+5443+02030	Europe/Kaliningrad	Moscow-01 - Kaliningrad
-RU	+5545+03735	Europe/Moscow	Moscow+00 - west Russia
-RU	+4844+04425	Europe/Volgograd	Moscow+00 - Caspian Sea
-RU	+5312+05009	Europe/Samara	Moscow+00 - Samara, Udmurtia
+RU	+554521+0373704	Europe/Moscow	Moscow+00 - west Russia
 RU	+4457+03406	Europe/Simferopol	Moscow+00 - Crimea
+RU	+4844+04425	Europe/Volgograd	Moscow+00 - Caspian Sea
+RU	+5312+05009	Europe/Samara	Moscow+00 (Moscow+01 after 2014-10-26) - Samara, Udmurtia
 RU	+5651+06036	Asia/Yekaterinburg	Moscow+02 - Urals
 RU	+5500+07324	Asia/Omsk	Moscow+03 - west Siberia
 RU	+5502+08255	Asia/Novosibirsk	Moscow+03 - Novosibirsk
-RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 - Novokuznetsk
+RU	+5345+08707	Asia/Novokuznetsk	Moscow+03 (Moscow+04 after 2014-10-26) - Kemerovo
 RU	+5601+09250	Asia/Krasnoyarsk	Moscow+04 - Yenisei River
 RU	+5216+10420	Asia/Irkutsk	Moscow+05 - Lake Baikal
+RU	+5203+11328	Asia/Chita	Moscow+06 (Moscow+05 after 2014-10-26) - Zabaykalsky
 RU	+6200+12940	Asia/Yakutsk	Moscow+06 - Lena River
 RU	+623923+1353314	Asia/Khandyga	Moscow+06 - Tomponsky, Ust-Maysky
 RU	+4310+13156	Asia/Vladivostok	Moscow+07 - Amur River
 RU	+4658+14242	Asia/Sakhalin	Moscow+07 - Sakhalin Island
 RU	+643337+1431336	Asia/Ust-Nera	Moscow+07 - Oymyakonsky
-RU	+5934+15048	Asia/Magadan	Moscow+08 - Magadan
-RU	+5301+15839	Asia/Kamchatka	Moscow+08 - Kamchatka
-RU	+6445+17729	Asia/Anadyr	Moscow+08 - Bering Sea
+RU	+5934+15048	Asia/Magadan	Moscow+08 (Moscow+07 after 2014-10-26) - Magadan
+RU	+6728+15343	Asia/Srednekolymsk	Moscow+08 - E Sakha, N Kuril Is
+RU	+5301+15839	Asia/Kamchatka	Moscow+08 (Moscow+09 after 2014-10-26) - Kamchatka
+RU	+6445+17729	Asia/Anadyr	Moscow+08 (Moscow+09 after 2014-10-26) - Bering Sea
 RW	-0157+03004	Africa/Kigali
 SA	+2438+04643	Asia/Riyadh
 SB	-0932+16012	Pacific/Guadalcanal
@@ -448,13 +435,13 @@ US	+394421-1045903	America/Denver	Mountain Time
 US	+433649-1161209	America/Boise	Mountain Time - south Idaho & east Oregon
 US	+332654-1120424	America/Phoenix	Mountain Standard Time - Arizona (except Navajo)
 US	+340308-1181434	America/Los_Angeles	Pacific Time
+US	+550737-1313435	America/Metlakatla	Pacific Standard Time - Annette Island, Alaska
 US	+611305-1495401	America/Anchorage	Alaska Time
 US	+581807-1342511	America/Juneau	Alaska Time - Alaska panhandle
 US	+571035-1351807	America/Sitka	Alaska Time - southeast Alaska panhandle
 US	+593249-1394338	America/Yakutat	Alaska Time - Alaska panhandle neck
 US	+643004-1652423	America/Nome	Alaska Time - west Alaska
 US	+515248-1763929	America/Adak	Aleutian Islands
-US	+550737-1313435	America/Metlakatla	Metlakatla Time - Annette Island
 US	+211825-1575130	Pacific/Honolulu	Hawaii
 UY	-3453-05611	America/Montevideo
 UZ	+3940+06648	Asia/Samarkand	west Uzbekistan
diff --git a/jdk/make/gendata/Gendata-java.base.gmk b/jdk/make/gendata/Gendata-java.base.gmk
index 71ee403d7a8..a7135abe563 100644
--- a/jdk/make/gendata/Gendata-java.base.gmk
+++ b/jdk/make/gendata/Gendata-java.base.gmk
@@ -62,25 +62,18 @@ GENDATA += $(GENDATA_CURDATA)
 
 ##########################################################################################
 
-PROPS_SRC := $(JDK_TOPDIR)/src/java.base/share/conf/security/java.security-$(OPENJDK_TARGET_OS)
-PROPS_DST := $(JDK_OUTPUTDIR)/lib/security/java.security
+GENDATA_JAVA_SECURITY_SRC := $(JDK_TOPDIR)/src/java.base/share/conf/security/java.security
+GENDATA_JAVA_SECURITY := $(JDK_OUTPUTDIR)/lib/security/java.security
 
-# Optionally set this variable to a file to add extra restricted packages.
-ifneq ($(RESTRICTED_PKGS_SRC), )
+# RESTRICTED_PKGS_SRC is optionally set in custom extension for this makefile
 
-  $(PROPS_DST): $(PROPS_SRC) $(RESTRICTED_PKGS_SRC)
+$(GENDATA_JAVA_SECURITY): $(BUILD_TOOLS) $(GENDATA_JAVA_SECURITY_SRC) $(RESTRICTED_PKGS_SRC)
+	$(ECHO) "Generating java.security"
 	$(MKDIR) -p $(@D)
-	$(TOOL_ADDTORESTRICTEDPKGS) $(PROPS_SRC) $@.tmp `$(CAT) $(RESTRICTED_PKGS_SRC) | $(TR) "\n" " "`
-	$(MV) $@.tmp $@
+	$(TOOL_MAKEJAVASECURITY) $(GENDATA_JAVA_SECURITY_SRC) $@ $(OPENJDK_TARGET_OS) \
+		$(RESTRICTED_PKGS_SRC) || exit 1
 
-else
-
-  $(PROPS_DST): $(PROPS_SRC)
-	$(call install-file)
-
-endif
-
-GENDATA += $(PROPS_DST)
+GENDATA += $(GENDATA_JAVA_SECURITY)
 
 ##########################################################################################
 
diff --git a/nashorn/bin/jjsdebug.sh b/jdk/make/gendata/Gendata-jdk.dev.gmk
similarity index 56%
rename from nashorn/bin/jjsdebug.sh
rename to jdk/make/gendata/Gendata-jdk.dev.gmk
index 509700c39bf..3c24cf4b703 100644
--- a/nashorn/bin/jjsdebug.sh
+++ b/jdk/make/gendata/Gendata-jdk.dev.gmk
@@ -1,25 +1,46 @@
-#!/bin/sh
 #
 # 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.
-# 
+# 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.
 #
 
-$JAVA_HOME/bin/jjs -J-Djava.ext.dirs=`dirname $0`/../dist -J-agentlib:jdwp=transport=dt_socket,address=localhost:9009,server=y,suspend=y $*
+include GendataCommon.gmk
+
+$(eval $(call IncludeCustomExtension, jdk, gendata/Gendata-jdk.dev.gmk))
+
+GENDATA := $(JDK_OUTPUTDIR)/modules/jdk.dev/com/sun/tools/jdeps/resources/jdeps-modules.xml
+METADATA_FILES += $(TOPDIR)/modules.xml
+
+#
+# Generate modules.xml for jdeps to use
+# It augments $(TOPDIR)/modules.xml to include module membership
+#
+$(GENDATA): $(BUILD_TOOLS_JDK) $(METADATA_FILES)
+	$(MKDIR) -p $(@D)
+	$(RM) $@
+	$(TOOL_GENMODULESXML) -o $@ -mp $(JDK_OUTPUTDIR)/modules $(METADATA_FILES)
+
+jdk.dev: $(GENDATA)
+
+all: $(GENDATA)
+
+.PHONY: all jdk.dev
diff --git a/jdk/make/gendata/GendataCommon.gmk b/jdk/make/gendata/GendataCommon.gmk
index c199a377378..e5e0336b325 100644
--- a/jdk/make/gendata/GendataCommon.gmk
+++ b/jdk/make/gendata/GendataCommon.gmk
@@ -28,9 +28,7 @@ default: all
 include $(SPEC)
 include MakeBase.gmk
 include JavaCompilation.gmk
-
-# Setup the java compilers for the JDK build.
-include SetupJava.gmk
+include SetupJavaCompilers.gmk
 # We need the tools.
 include Tools.gmk
 
diff --git a/jdk/make/gensrc/GensrcCommon.gmk b/jdk/make/gensrc/GensrcCommon.gmk
index 3c271c81d77..09819e19d57 100644
--- a/jdk/make/gensrc/GensrcCommon.gmk
+++ b/jdk/make/gensrc/GensrcCommon.gmk
@@ -30,9 +30,7 @@ include MakeBase.gmk
 include JavaCompilation.gmk
 include NativeCompilation.gmk
 include TextFileProcessing.gmk
-
-# Setup the java compilers for the JDK build.
-include SetupJava.gmk
+include SetupJavaCompilers.gmk
 # We need the tools.
 include Tools.gmk
 
diff --git a/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk b/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk
index b3f0335d7e0..b251026c2cb 100644
--- a/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk
+++ b/jdk/make/gensrc/GensrcLocaleDataMetaInfo.gmk
@@ -1,5 +1,5 @@
 #
-# Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
+# Copyright (c) 2011, 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
@@ -28,13 +28,15 @@
 # into LocaleDataMetaInfo.java
 
 # First go look for all locale files
-LOCALE_FILES := $(shell $(FIND) $(JDK_TOPDIR)/src/*/share/classes \
+LOCALE_FILES := $(shell $(FIND) $(JDK_TOPDIR)/src/java.base/share/classes \
+    $(JDK_TOPDIR)/src/jdk.localedata/share/classes \
     -name "FormatData_*.java" -o -name "FormatData_*.properties" -o \
     -name "CollationData_*.java" -o -name "CollationData_*.properties" -o \
     -name "TimeZoneNames_*.java" -o -name "TimeZoneNames_*.properties" -o \
     -name "LocaleNames_*.java" -o -name "LocaleNames_*.properties" -o \
     -name "CurrencyNames_*.java" -o -name "CurrencyNames_*.properties" -o \
-    -name "CalendarData_*.java" -o -name "CalendarData_*.properties")
+    -name "CalendarData_*.java" -o -name "CalendarData_*.properties" -o \
+    -name "BreakIteratorInfo_*.java" -o -name "BreakIteratorRules_*.java")
 
 # Then translate the locale files into for example: FormatData_sv
 LOCALE_RESOURCES := $(sort $(subst .properties,,$(subst .java,,$(notdir $(LOCALE_FILES)))))
@@ -56,7 +58,14 @@ EN_LOCALES := en%
 # Locales that don't have any resource files should be included here.
 ALL_NON_EN_LOCALES := ja-JP-JP nb-NO nn-NO th-TH-TH
 
-SED_ARGS := -e 's|$(HASH)warn This file is preprocessed before being compiled|// -- This file was mechanically generated: Do not edit! -- //|g'
+SED_ENARGS := -e 's|$(HASH)warn This file is preprocessed before being compiled|// -- This file was mechanically generated: Do not edit! -- //|g'
+SED_NONENARGS := $(SED_ENARGS)
+
+# Fill in the languages and package names
+SED_ENARGS += -e 's/$(HASH)Lang$(HASH)/En/' \
+    -e 's/$(HASH)Package$(HASH)/sun.util.locale.provider/'
+SED_NONENARGS += -e 's/$(HASH)Lang$(HASH)/NonEn/' \
+    -e 's/$(HASH)Package$(HASH)/sun.util.resources.provider/'
 
 # This macro creates a sed expression that substitues for example:
 # #FormatData_ENLocales# with: en% locales.
@@ -76,8 +85,8 @@ define CaptureLocale
   ALL_NON_EN_LOCALES += $$($1_NON_EN_LOCALES)
 
   # Don't sed in a space if there are no locales.
-  SED_ARGS += -e 's/$$(HASH)$1_ENLocales$$(HASH)/$$(if $$($1_EN_LOCALES),$$(SPACE)$$($1_EN_LOCALES),)/g'
-  SED_ARGS += -e 's/$$(HASH)$1_NonENLocales$$(HASH)/$$(if $$($1_NON_EN_LOCALES),$$(SPACE)$$($1_NON_EN_LOCALES),)/g'
+  SED_ENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_EN_LOCALES),$$(SPACE)$$($1_EN_LOCALES),)/g'
+  SED_NONENARGS += -e 's/$$(HASH)$1_Locales$$(HASH)/$$(if $$($1_NON_EN_LOCALES),$$(SPACE)$$($1_NON_EN_LOCALES),)/g'
 endef
 
 #sun.text.resources.FormatData
@@ -86,6 +95,12 @@ $(eval $(call CaptureLocale,FormatData))
 #sun.text.resources.CollationData
 $(eval $(call CaptureLocale,CollationData))
 
+#sun.text.resources.BreakIteratorInfo
+$(eval $(call CaptureLocale,BreakIteratorInfo))
+
+#sun.text.resources.BreakIteratorRules
+$(eval $(call CaptureLocale,BreakIteratorRules))
+
 #sun.util.resources.TimeZoneNames
 $(eval $(call CaptureLocale,TimeZoneNames))
 
@@ -98,17 +113,25 @@ $(eval $(call CaptureLocale,CurrencyNames))
 #sun.util.resources.CalendarData
 $(eval $(call CaptureLocale,CalendarData))
 
-SED_ARGS += -e 's/$(HASH)AvailableLocales_ENLocales$(HASH)/$(sort $(ALL_EN_LOCALES))/g'
-SED_ARGS += -e 's/$(HASH)AvailableLocales_NonENLocales$(HASH)/$(sort $(ALL_NON_EN_LOCALES))/g'
+SED_ENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_EN_LOCALES))/g'
+SED_NONENARGS += -e 's/$(HASH)AvailableLocales_Locales$(HASH)/$(sort $(ALL_NON_EN_LOCALES))/g'
 
-$(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/LocaleDataMetaInfo.java: \
+$(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java: \
     $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template
 	$(MKDIR) -p $(@D)
-	$(ECHO) Creating sun/util/LocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources.
+	$(ECHO) Creating sun/util/locale/provider/EnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources.
 	$(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
-	$(SED) $(SED_ARGS) $< > $@
+	$(SED) $(SED_ENARGS) $< > $@
 
-GENSRC_LOCALEDATAMETAINFO := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/LocaleDataMetaInfo.java
+$(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java: \
+    $(JDK_TOPDIR)/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template
+	$(MKDIR) -p $(@D)
+	$(ECHO) Creating sun/util/resources/provider/NonEnLocaleDataMetaInfo.java from $(words $(LOCALE_RESOURCES)) found resources.
+	$(PRINTF) "PREV_LOCALE_RESOURCES:=$(LOCALE_RESOURCES)" > $(JDK_OUTPUTDIR)/gensrc/_the.locale_resources
+	$(SED) $(SED_NONENARGS) $< > $@
+
+GENSRC_LOCALEDATAMETAINFO := $(JDK_OUTPUTDIR)/gensrc/java.base/sun/util/locale/provider/EnLocaleDataMetaInfo.java \
+    $(JDK_OUTPUTDIR)/gensrc/jdk.localedata/sun/util/resources/provider/NonEnLocaleDataMetaInfo.java
 
 ################################################################################
 
diff --git a/jdk/make/gensrc/GensrcProperties.gmk b/jdk/make/gensrc/GensrcProperties.gmk
index c387d52ffe2..a33015b150c 100644
--- a/jdk/make/gensrc/GensrcProperties.gmk
+++ b/jdk/make/gensrc/GensrcProperties.gmk
@@ -23,9 +23,6 @@
 # questions.
 #
 
-# Prepare the find cache.
-$(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/*/*/classes)))
-
 # All .properties files to be compiled are appended to this variable.
 ALL_COMPILED_PROPSOURCES :=
 # All generated .java files from compilation are appended to this variable.
@@ -76,7 +73,6 @@ COMPILE_PROP_SRC_FILES := \
         $(JDK_TOPDIR)/src/java.management/share/classes/sun/management/resources \
         $(JDK_TOPDIR)/src/java.desktop/share/classes/sun/print/resources \
         $(JDK_TOPDIR)/src/jdk.dev/share/classes/sun/tools/jar/resources \
-        $(JDK_TOPDIR)/src/jdk.dev/share/classes/jdk/jigsaw/tools/jlink/resources \
         $(JDK_TOPDIR)/src/java.logging/share/classes/sun/util/logging/resources)) \
     #
 
diff --git a/jdk/make/gensrc/GensrcProviders.gmk b/jdk/make/gensrc/GensrcProviders.gmk
index 985f032169e..dca14083054 100644
--- a/jdk/make/gensrc/GensrcProviders.gmk
+++ b/jdk/make/gensrc/GensrcProviders.gmk
@@ -32,15 +32,6 @@ endef
 
 ################################################################################
 
-# Filter com.sun.tools.attach.spi.AttachProvider
-$(JDK_OUTPUTDIR)/gensrc/jdk.attach/META-INF/services/com.sun.tools.attach.spi.AttachProvider: \
-    $(JDK_TOPDIR)/src/jdk.attach/share/classes/META-INF/services/com.sun.tools.attach.spi.AttachProvider
-	$(process-provider)
-
-GENSRC_JDK_ATTACH += $(JDK_OUTPUTDIR)/gensrc/jdk.attach/META-INF/services/com.sun.tools.attach.spi.AttachProvider
-
-################################################################################
-
 # Filter com.sun.jdi.connect.Connector
 $(JDK_OUTPUTDIR)/gensrc/jdk.jdi/META-INF/services/com.sun.jdi.connect.Connector: \
     $(JDK_TOPDIR)/src/jdk.jdi/share/classes/META-INF/services/com.sun.jdi.connect.Connector
diff --git a/jdk/make/gensrc/GensrcSwing.gmk b/jdk/make/gensrc/GensrcSwing.gmk
index 12e2445bb32..c7571269c98 100644
--- a/jdk/make/gensrc/GensrcSwing.gmk
+++ b/jdk/make/gensrc/GensrcSwing.gmk
@@ -78,11 +78,8 @@ $(JDK_OUTPUTDIR)/gensrc_no_srczip/_the.generated_beaninfo: $(BEANS_SRC) \
 	$(MKDIR) -p $(JDK_OUTPUTDIR)/gensrc_no_srczip/java.desktop/javax/swing
 	$(JAVA) -Djava.awt.headless=true $(NEW_JAVADOC) \
 	    -sourcepath "$(subst $(SPACE),$(PATH_SEP),\
-	        $(if $(SHUFFLED),$(wildcard $(JDK_TOPDIR)/src/*/*/classes) \
-	        $(JDK_OUTPUTDIR)/gensrc/java.base, \
-	        $(JDK_TOPDIR)/src/share/classes \
-                $(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/classes \
-	        $(JDK_OUTPUTDIR)/gensrc))" \
+	        $(wildcard $(JDK_TOPDIR)/src/*/*/classes) \
+	        $(JDK_OUTPUTDIR)/gensrc/java.base)" \
 	    -doclet build.tools.swingbeaninfo.GenDocletBeanInfo \
 	    -x $(SWINGBEAN_DEBUG_FLAG) -d $(JDK_OUTPUTDIR)/gensrc_no_srczip/java.desktop/javax/swing \
 	    -t $(DOCLET_DATA_DIR)/SwingBeanInfo.template -docletpath $(JDK_OUTPUTDIR)/btclasses \
diff --git a/jdk/make/lib/Awt2dLibraries.gmk b/jdk/make/lib/Awt2dLibraries.gmk
index 774a2675836..e5161a35552 100644
--- a/jdk/make/lib/Awt2dLibraries.gmk
+++ b/jdk/make/lib/Awt2dLibraries.gmk
@@ -23,12 +23,9 @@
 # questions.
 #
 
-# Hook to include the corresponding custom file, if present.
-$(eval $(call IncludeCustomExtension, jdk, lib/Awt2dLibraries.gmk))
-
 WIN_AWT_LIB := $(JDK_OUTPUTDIR)/objs/libawt/awt.lib
 
-##########################################################################################
+################################################################################
 
 BUILD_LIBMLIB_SRC := $(JDK_TOPDIR)/src/java.desktop/share/native/libmlib_image \
     $(JDK_TOPDIR)/src/java.desktop/share/native/common/sun/awt/medialib
@@ -76,7 +73,7 @@ $(BUILD_LIBMLIB_IMAGE): $(BUILD_LIBJAVA)
 
 DESKTOP_LIBRARIES += $(BUILD_LIBMLIB_IMAGE)
 
-##########################################################################################
+################################################################################
 
 ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc)
 
@@ -144,7 +141,7 @@ ifeq ($(OPENJDK_TARGET_OS)-$(OPENJDK_TARGET_CPU_ARCH), solaris-sparc)
 
 endif
 
-##########################################################################################
+################################################################################
 
 LIBAWT_DIRS := $(JDK_TOPDIR)/src/java.desktop/share/native/libawt \
     $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/libawt \
@@ -152,13 +149,17 @@ LIBAWT_DIRS := $(JDK_TOPDIR)/src/java.desktop/share/native/libawt \
     $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/common/sun/awt \
     #
 
+ifeq ($(OPENJDK_TARGET_OS), aix)
+  LIBAWT_DIRS += $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS)/native/libawt
+endif
+
 ifeq ($(OPENJDK_TARGET_OS), windows)
   LIBAWT_DIRS += $(JDK_TOPDIR)/src/java.desktop/share/native/common/sun/awt/utility
 else
   LIBAWT_EXFILES := sun/java2d/ShaderList.c
 endif
 
-ifneq ($(filter $(OPENJDK_TARGET_OS), solaris linux macosx), )
+ifneq ($(filter $(OPENJDK_TARGET_OS), solaris linux macosx aix), )
   LIBAWT_EXFILES += awt_Font.c CUPSfuncs.c fontpath.c X11Color.c
 endif
 
@@ -168,14 +169,11 @@ endif
 
 LIBAWT_CFLAGS += -I$(JDK_OUTPUTDIR)/gensrc_headers/java.desktop \
     $(addprefix -I, $(shell find $(LIBAWT_DIRS) -type d)) \
-    -I$(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/common/sun/awt \
     $(LIBJAVA_HEADER_FLAGS) \
     $(addprefix -I, $(BUILD_LIBMLIB_IMAGE_SRC)) \
     #
 
-LIBAWT_CFLAGS += -D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES \
-    $(X_CFLAGS) \
-    $(foreach dir, $(LIBAWT_DIRS), -I$(dir))
+LIBAWT_CFLAGS += -D__MEDIALIB_OLD_NAMES -D__USE_J2D_NAMES $(X_CFLAGS)
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
 endif
@@ -296,7 +294,7 @@ endif
 
 DESKTOP_LIBRARIES += $(BUILD_LIBAWT)
 
-##########################################################################################
+################################################################################
 
 ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),)
   ifndef BUILD_HEADLESS_ONLY
@@ -388,7 +386,7 @@ ifeq ($(findstring $(OPENJDK_TARGET_OS),windows macosx),)
   endif
 endif
 
-##########################################################################################
+################################################################################
 
 LIBLCMS_SRC := $(JDK_TOPDIR)/src/java.desktop/share/native/liblcms
 LIBLCMS_CPPFLAGS += -I$(JDK_OUTPUTDIR)/gensrc_headers/java.desktop \
@@ -441,7 +439,7 @@ DESKTOP_LIBRARIES += $(BUILD_LIBLCMS)
 
 $(BUILD_LIBLCMS): $(BUILD_LIBAWT)
 
-##########################################################################################
+################################################################################
 
 ifdef OPENJDK
   BUILD_LIBJAVAJPEG_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjpeg/mapfile-vers
@@ -515,7 +513,7 @@ $(BUILD_LIBJAVAJPEG): $(BUILD_LIBJAVA)
 
 DESKTOP_LIBRARIES += $(BUILD_LIBJAVAJPEG)
 
-##########################################################################################
+################################################################################
 
 LIBFONTMANAGER_SRC := $(JDK_TOPDIR)/src/java.desktop/share/native/libfontmanager \
     $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/libfontmanager
@@ -607,54 +605,7 @@ endif
 
 DESKTOP_LIBRARIES += $(BUILD_LIBFONTMANAGER)
 
-##########################################################################################
-
-ifndef OPENJDK
-
-  LIBT2K_SRC := $(JDK_TOPDIR)/src/closed/java.desktop/share/native/libt2k
-  LIBT2K_CFLAGS := $(addprefix -I, $(LIBT2K_SRC)) \
-      -I$(JDK_TOPDIR)/src/closed/java.desktop/share/native/libt2k/t2k \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libfontmanager \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/sun/java2d \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/sun/java2d/loops \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/common/sun/font \
-      -I$(JDK_TOPDIR)/src/java.base/share/native/libjava \
-      -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_API_DIR)/native/libjava \
-      -I$(JDK_OUTPUTDIR)/gensrc_headers/java.desktop \
-  #
-
-  $(eval $(call SetupNativeCompilation,BUILD_LIBT2K, \
-      LIBRARY := t2k, \
-      OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-      SRC := $(LIBT2K_SRC), \
-      EXCLUDE_FILES := t2k/orion.c, \
-      LANG := C++, \
-      OPTIMIZATION := HIGH, \
-      CFLAGS := $(CFLAGS_JDKLIB) $(LIBT2K_CFLAGS), \
-      CXXFLAGS := $(CXXFLAGS_JDKLIB) $(LIBT2K_CFLAGS), \
-      CFLAGS_windows = -DCC_NOEX, \
-      CXXFLAGS_windows = -DCC_NOEX, \
-      MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libt2k/mapfile-vers, \
-      LDFLAGS := $(LDFLAGS_JDKLIB) $(LDFLAGS_CXX_JDK) \
-          $(call SET_SHARED_LIBRARY_ORIGIN), \
-      LDFLAGS_windows := user32.lib $(JDK_OUTPUTDIR)/objs/libfontmanager/fontmanager.lib, \
-      LDFLAGS_SUFFIX_posix := $(LIBM) $(LIBCXX) -lfontmanager -ljava -ljvm -lc, \
-      LDFLAGS_SUFFIX_solaris := -lawt -lawt_xawt, \
-      VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
-      RC_FLAGS := $(RC_FLAGS) \
-          -D "JDK_FNAME=t2k.dll" \
-          -D "JDK_INTERNAL_NAME=t2k" \
-          -D "JDK_FTYPE=0x2L", \
-      OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libt2k, \
-      DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
-
-  # t2k is linked against fontmanager
-  $(BUILD_LIBT2K): $(BUILD_LIBFONTMANAGER)
-
-  DESKTOP_LIBRARIES += $(BUILD_LIBT2K)
-endif
-
-##########################################################################################
+################################################################################
 
 ifeq ($(OPENJDK_TARGET_OS), windows)
   LIBJAWT_SRC := $(JDK_TOPDIR)/src/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/libjawt
@@ -768,99 +719,7 @@ endif # OPENJDK_TARGET_OS
 
 DESKTOP_LIBRARIES += $(BUILD_LIBJAWT)
 
-##########################################################################################
-
-ifndef OPENJDK
-
-  LIBKCMS_SRC := $(JDK_TOPDIR)/src/closed/java.desktop/share/native/libkcms \
-      $(JDK_TOPDIR)/src/closed/java.desktop/$(OPENJDK_TARGET_OS_API_DIR)/native/libkcms \
-      #
-  LIBKCMS_CFLAGS += $(addprefix -I, $(LIBKCMS_SRC)) \
-      -I$(JDK_TOPDIR)/src/java.base/share/native/libjava \
-      -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_API_DIR)/native/libjava \
-      -I$(JDK_OUTPUTDIR)/gensrc_headers/java.desktop \
-      #
-  LIBKCMS_VERSIONINFO_RESOURCE := $(JDK_TOPDIR)/src/closed/java.desktop/windows/native/libkcms/cmm.rc
-
-  LIBKCMS_CFLAGS += $(CFLAGS_JDKLIB)
-
-  ifeq ($(OPENJDK_TARGET_OS), solaris)
-    # This particular library uses a feature called PIC_CODE_SMALL (on solaris)
-    # implement it like this...since it's only used here
-    LIBKCMS_CFLAGS := $(patsubst -KPIC, -Kpic, $(LIBKCMS_CFLAGS))
-  else ifeq ($(OPENJDK_TARGET_CPU_ARCH), ppc)
-    LIBKCMS_CFLAGS := $(patsubst -fPIC, -fpic, $(LIBKCMS_CFLAGS))
-  endif
-
-  $(eval $(call SetupNativeCompilation,BUILD_LIBKCMS, \
-      LIBRARY := kcms, \
-      OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-      SRC := $(LIBKCMS_SRC), \
-      LANG := C, \
-      EXCLUDE_FILES := $(BUILD_LIBKCMS_EXCLUDE_FILES), \
-      OPTIMIZATION := LOW, \
-      CFLAGS := $(LIBKCMS_CFLAGS) \
-          -DJAVACMM -DFUT_CALC_EX -DNO_FUT_GCONST, \
-      CFLAGS_linux := -Wno-missing-field-initializers, \
-      MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libkcms/mapfile-vers, \
-      LDFLAGS := $(LDFLAGS_JDKLIB) \
-          $(call SET_SHARED_LIBRARY_ORIGIN), \
-      LDFLAGS_SUFFIX_linux := -lc -lpthread, \
-      LDFLAGS_SUFFIX_solaris := -lc, \
-      LDFLAGS_SUFFIX_windows := $(WIN_JAVA_LIB) advapi32.lib user32.lib version.lib, \
-      LDFLAGS_SUFFIX_posix := -lm -ljava -ljvm, \
-      VERSIONINFO_RESOURCE := $(LIBKCMS_VERSIONINFO_RESOURCE), \
-      RC_FLAGS := $(RC_FLAGS) \
-          -D "JDK_FNAME=kcms.dll" \
-          -D "JDK_INTERNAL_NAME=kcms" \
-          -D "JDK_FTYPE=0x2L", \
-      OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libkcms, \
-      DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
-
-  $(BUILD_LIBKCMS): $(BUILD_LIBJAVA)
-
-  DESKTOP_LIBRARIES += $(BUILD_LIBKCMS)
-
-endif
-
-##########################################################################################
-
-ifndef OPENJDK
-  ifeq ($(OPENJDK_TARGET_OS), solaris)
-    ifneq ($(OPENJDK_TARGET_CPU), x86_64)
-
-      ifeq ($(shell if test "$(OS_VERSION_MAJOR)" -eq 5 -a "$(OS_VERSION_MINOR)" -le 10; then $(ECHO) ok; fi), ok)
-
-        SUNWJDGA_MAPFILE :=
-        ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc)
-          SUNWJDGA_MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libjdga/mapfile-vers
-        endif
-
-        $(eval $(call SetupNativeCompilation,BUILD_LIBSUNWJDGA, \
-            LIBRARY := sunwjdga, \
-            OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-            SRC := $(JDK_TOPDIR)/src/java.desktop/unix/native/libsunwjdga, \
-            LANG := C, \
-            OPTIMIZATION := LOW, \
-            CFLAGS := $(CFLAGS_JDKLIB) \
-                -I$(JDK_TOPDIR)/src/share/javavm/export \
-                -I$(JDK_TOPDIR)/src/$(OPENJDK_TARGET_OS_API_DIR)/javavm/export \
-                $(X_CFLAGS), \
-            MAPFILE := $(SUNWJDGA_MAPFILE), \
-            LDFLAGS := $(LDFLAGS_JDKLIB) \
-                $(call SET_SHARED_LIBRARY_ORIGIN), \
-            LDFLAGS_SUFFIX := $(X_LIBS) -ldga -lX11 $(LIBDL) -lc, \
-            OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libsunwjdga, \
-            DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
-
-        DESKTOP_LIBRARIES += $(BUILD_LIBSUNWJDGA)
-
-      endif
-    endif
-  endif
-endif
-
-##########################################################################################
+################################################################################
 
 ifeq ($(BUILD_HEADLESS), true)
   # Mac and Windows only use the native AWT lib, do not build libawt_headless
@@ -932,7 +791,7 @@ ifeq ($(BUILD_HEADLESS), true)
   endif
 endif
 
-##########################################################################################
+################################################################################
 
 ifndef BUILD_HEADLESS_ONLY
 
@@ -973,7 +832,6 @@ ifndef BUILD_HEADLESS_ONLY
       #
 
   ifeq ($(OPENJDK_TARGET_OS), macosx)
-    LIBSPLASHSCREEN_CFLAGS += -F/System/Library/Frameworks/JavaVM.framework/Frameworks
     LIBSPLASHSCREEN_CFLAGS += -DWITH_MACOSX
     LIBSPLASHSCREEN_CFLAGS += -I$(JDK_TOPDIR)/src/java.desktop/macosx/native/libosxapp
 
@@ -1042,47 +900,7 @@ ifndef BUILD_HEADLESS_ONLY
 
 endif
 
-##########################################################################################
-
-ifndef OPENJDK
-
-  LIBDCPR_SRC_DIRS := $(JDK_TOPDIR)/src/closed/java.desktop/share/native/libdcpr
-  LIBDCPR_CFLAGS := $(addprefix -I, $(shell $(FIND) $(LIBDCPR_SRC_DIRS) -type d)) \
-      -I$(JDK_TOPDIR)/src/java.desktop/share/native/libawt/sun/java2d/pipe \
-      -I$(JDK_TOPDIR)/src/java.base/share/native/libjava \
-      -I$(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS_API_DIR)/native/libjava \
-      -I$(JDK_OUTPUTDIR)/gensrc_headers/java.desktop \
-      #
-
-  $(eval $(call SetupNativeCompilation,BUILD_LIBDCPR, \
-      LIBRARY := dcpr, \
-      OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-      SRC := $(LIBDCPR_SRC_DIRS), \
-      LANG := C, \
-      OPTIMIZATION := LOW, \
-      CFLAGS := $(CFLAGS_JDKLIB) \
-          $(LIBDCPR_CFLAGS), \
-      MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libdcpr/mapfile-vers, \
-      LDFLAGS := $(LDFLAGS_JDKLIB) \
-          $(call SET_SHARED_LIBRARY_ORIGIN), \
-      LDFLAGS_SUFFIX := $(LIBM) $(LDFLAGS_JDKLIB_SUFFIX), \
-      LDFLAGS_SUFFIX_windows := $(WIN_JAVA_LIB), \
-      LDFLAGS_SUFFIX_posix := -lm, \
-      VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
-      RC_FLAGS := $(RC_FLAGS) \
-          -D "JDK_FNAME=dcpr.dll" \
-          -D "JDK_INTERNAL_NAME=dcpr" \
-          -D "JDK_FTYPE=0x2L", \
-      OBJECT_DIR := $(JDK_OUTPUTDIR)/objs/libdcpr, \
-      DEBUG_SYMBOLS := $(DEBUG_ALL_BINARIES)))
-
-  $(BUILD_LIBDCPR): $(BUILD_LIBJAVA)
-
-  DESKTOP_LIBRARIES += $(BUILD_LIBDCPR)
-
-endif
-
-##########################################################################################
+################################################################################
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
 
@@ -1159,7 +977,7 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
 
 endif
 
-##########################################################################################
+################################################################################
 
 ifeq ($(OPENJDK_TARGET_OS), macosx)
 
@@ -1200,3 +1018,8 @@ ifeq ($(OPENJDK_TARGET_OS), macosx)
   #$(BUILD_LIBOSXUI): $(BUILD_LIBJAVA)
 
 endif
+
+################################################################################
+
+# Hook to include the corresponding custom file, if present.
+$(eval $(call IncludeCustomExtension, jdk, lib/Awt2dLibraries.gmk))
diff --git a/jdk/make/lib/CoreLibraries.gmk b/jdk/make/lib/CoreLibraries.gmk
index 99a0c46f114..852879f09ee 100644
--- a/jdk/make/lib/CoreLibraries.gmk
+++ b/jdk/make/lib/CoreLibraries.gmk
@@ -26,6 +26,8 @@
 WIN_VERIFY_LIB := $(JDK_OUTPUTDIR)/objs/libverify/verify.lib
 
 ##########################################################################################
+# libfdlibm is statically linked with libjava below and not delivered into the 
+# product on its own.
 
 BUILD_LIBFDLIBM_OPTIMIZATION := HIGH
 
diff --git a/jdk/make/lib/Lib-java.base.gmk b/jdk/make/lib/Lib-java.base.gmk
index cf7f663d6fa..301e31c2df8 100644
--- a/jdk/make/lib/Lib-java.base.gmk
+++ b/jdk/make/lib/Lib-java.base.gmk
@@ -25,6 +25,10 @@
 
 include LibCommon.gmk
 
+# Prepare the find cache.
+$(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/java.base/*/native \
+    $(JDK_TOPDIR)/src/*/java.base/*/native)))
+
 include CoreLibraries.gmk
 include NetworkingLibraries.gmk
 include NioLibraries.gmk
diff --git a/jdk/make/lib/Lib-java.desktop.gmk b/jdk/make/lib/Lib-java.desktop.gmk
index bdd919cfeb7..e8661508e93 100644
--- a/jdk/make/lib/Lib-java.desktop.gmk
+++ b/jdk/make/lib/Lib-java.desktop.gmk
@@ -25,6 +25,10 @@
 
 include LibCommon.gmk
 
+# Prepare the find cache.
+$(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/java.desktop/*/native \
+    $(JDK_TOPDIR)/src/*/java.desktop/*/native)))
+
 include PlatformLibraries.gmk
 include Awt2dLibraries.gmk
 include SoundLibraries.gmk
diff --git a/jdk/make/lib/Lib-jdk.attach.gmk b/jdk/make/lib/Lib-jdk.attach.gmk
index 65b7b1397d7..2b58e173efb 100644
--- a/jdk/make/lib/Lib-jdk.attach.gmk
+++ b/jdk/make/lib/Lib-jdk.attach.gmk
@@ -27,33 +27,11 @@ include LibCommon.gmk
 
 ################################################################################
 
-ifeq ($(OPENJDK_TARGET_OS), aix)
-  LIBATTACH_OS_API_DIR := aix
-else
-  LIBATTACH_OS_API_DIR := $(OPENJDK_TARGET_OS_API_DIR)
-endif
-
-LIBATTACH_SRC := $(JDK_TOPDIR)/src/jdk.attach/$(LIBATTACH_OS_API_DIR)/native/libattach
-
-LIBATTACH_EXCLUDE_FILES :=
-ifneq ($(OPENJDK_TARGET_OS), solaris)
-  LIBATTACH_EXCLUDE_FILES += SolarisVirtualMachine.c
-endif
-ifneq ($(OPENJDK_TARGET_OS), linux)
-  LIBATTACH_EXCLUDE_FILES += LinuxVirtualMachine.c
-endif
-ifneq ($(OPENJDK_TARGET_OS), macosx)
-  LIBATTACH_EXCLUDE_FILES += BsdVirtualMachine.c
-endif
-ifneq ($(OPENJDK_TARGET_OS),aix)
-  LIBATTACH_EXCLUDE_FILES += AixVirtualMachine.c
-endif
 
 $(eval $(call SetupNativeCompilation,BUILD_LIBATTACH, \
     LIBRARY := attach, \
     OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \
-    SRC := $(LIBATTACH_SRC), \
-    EXCLUDE_FILES := $(LIBATTACH_EXCLUDE_FILES), \
+    SRC := $(JDK_TOPDIR)/src/jdk.attach/$(OPENJDK_TARGET_OS)/native/libattach, \
     LANG := C, \
     OPTIMIZATION := LOW, \
     CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) \
diff --git a/jdk/make/lib/Lib-jdk.hprof.agent.gmk b/jdk/make/lib/Lib-jdk.hprof.agent.gmk
index 7b7ef69b2e0..a58687da251 100644
--- a/jdk/make/lib/Lib-jdk.hprof.agent.gmk
+++ b/jdk/make/lib/Lib-jdk.hprof.agent.gmk
@@ -27,11 +27,11 @@ include LibCommon.gmk
 
 ################################################################################
 
-BUILD_LIBHPROF_SRC := $(JDK_TOPDIR)/src/demo/share/jvmti/hprof \
-    $(JDK_TOPDIR)/src/demo/$(OPENJDK_TARGET_OS_API_DIR)/jvmti/hprof
+BUILD_LIBHPROF_SRC := $(call FindSrcDirsForLib, jdk.hprof.agent, hprof)
+
 BUILD_LIBHPROF_CFLAGS := $(addprefix -I, $(BUILD_LIBHPROF_SRC)) \
     -I$(JDK_TOPDIR)/src/demo/share/jvmti/java_crw_demo
-
+    
 BUILD_LIBHPROF_LDFLAGS :=
 
 LIBHPROF_OPTIMIZATION := HIGHEST
diff --git a/jdk/make/lib/LibCommon.gmk b/jdk/make/lib/LibCommon.gmk
index 7fadd1c781f..885ba11c780 100644
--- a/jdk/make/lib/LibCommon.gmk
+++ b/jdk/make/lib/LibCommon.gmk
@@ -29,9 +29,6 @@ include $(SPEC)
 include MakeBase.gmk
 include NativeCompilation.gmk
 
-# Prepare the find cache.
-$(eval $(call FillCacheFind, $(wildcard $(JDK_TOPDIR)/src/*/*/native)))
-
 # Build tools
 include Tools.gmk
 
diff --git a/jdk/make/lib/NetworkingLibraries.gmk b/jdk/make/lib/NetworkingLibraries.gmk
index e61f80be925..a0825b06ce2 100644
--- a/jdk/make/lib/NetworkingLibraries.gmk
+++ b/jdk/make/lib/NetworkingLibraries.gmk
@@ -44,7 +44,7 @@ ifneq ($(OPENJDK_TARGET_OS), macosx)
 endif
 
 ifeq ($(OPENJDK_TARGET_OS), aix)
-  LIBNET_SRC_DIRS += $(JDK_TOPDIR)/src/aix/native/java/net/
+  LIBNET_SRC_DIRS += $(JDK_TOPDIR)/src/java.base/$(OPENJDK_TARGET_OS)/native/libnet/java/net/
 endif
 
 $(eval $(call SetupNativeCompilation,BUILD_LIBNET, \
diff --git a/jdk/make/lib/NioLibraries.gmk b/jdk/make/lib/NioLibraries.gmk
index 259517c2aad..722115fdee5 100644
--- a/jdk/make/lib/NioLibraries.gmk
+++ b/jdk/make/lib/NioLibraries.gmk
@@ -56,17 +56,8 @@ endif
 
 ifeq ($(OPENJDK_TARGET_OS), aix)
   BUILD_LIBNIO_MAPFILE:=$(JDK_TOPDIR)/make/mapfiles/libnio/mapfile-$(OPENJDK_TARGET_OS)
-  BUILD_LIBNIO_FILES += \
-      AixPollPort.c \
-      InheritedChannel.c \
-      AixNativeThread.c \
-      PollArrayWrapper.c \
-      UnixAsynchronousServerSocketChannelImpl.c \
-      UnixAsynchronousSocketChannelImpl.c \
-      GnomeFileTypeDetector.c \
-      UnixCopyFile.c \
-      AixNativeDispatcher.c \
-      UnixNativeDispatcher.c
+  BUILD_LIBNIO_EXFILES += \
+      NativeThread.c
 endif
 
 $(eval $(call SetupNativeCompilation,BUILD_LIBNIO, \
diff --git a/jdk/make/mapfiles/libattach/mapfile-aix b/jdk/make/mapfiles/libattach/mapfile-aix
index 4c02da01fce..10ca49534ba 100644
--- a/jdk/make/mapfiles/libattach/mapfile-aix
+++ b/jdk/make/mapfiles/libattach/mapfile-aix
@@ -27,13 +27,13 @@
 
 SUNWprivate_1.1 {
 	global:
-            Java_sun_tools_attach_AixVirtualMachine_socket
-            Java_sun_tools_attach_AixVirtualMachine_connect
-            Java_sun_tools_attach_AixVirtualMachine_sendQuitTo
-            Java_sun_tools_attach_AixVirtualMachine_checkPermissions
-            Java_sun_tools_attach_AixVirtualMachine_close
-            Java_sun_tools_attach_AixVirtualMachine_read
-            Java_sun_tools_attach_AixVirtualMachine_write
+            Java_sun_tools_attach_VirtualMachineImpl_socket
+            Java_sun_tools_attach_VirtualMachineImpl_connect
+            Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo
+            Java_sun_tools_attach_VirtualMachineImpl_checkPermissions
+            Java_sun_tools_attach_VirtualMachineImpl_close
+            Java_sun_tools_attach_VirtualMachineImpl_read
+            Java_sun_tools_attach_VirtualMachineImpl_write
 	local:
 		*;
 };
diff --git a/jdk/make/mapfiles/libattach/mapfile-linux b/jdk/make/mapfiles/libattach/mapfile-linux
index fbfdedfdad9..b569ae5e637 100644
--- a/jdk/make/mapfiles/libattach/mapfile-linux
+++ b/jdk/make/mapfiles/libattach/mapfile-linux
@@ -27,17 +27,17 @@
 
 SUNWprivate_1.1 {
 	global:
-	    Java_sun_tools_attach_LinuxVirtualMachine_checkPermissions;
-	    Java_sun_tools_attach_LinuxVirtualMachine_close;
-	    Java_sun_tools_attach_LinuxVirtualMachine_connect;
-	    Java_sun_tools_attach_LinuxVirtualMachine_getLinuxThreadsManager;
-	    Java_sun_tools_attach_LinuxVirtualMachine_isLinuxThreads;
-	    Java_sun_tools_attach_LinuxVirtualMachine_open;
-	    Java_sun_tools_attach_LinuxVirtualMachine_sendQuitTo;
-            Java_sun_tools_attach_LinuxVirtualMachine_sendQuitToChildrenOf;
-	    Java_sun_tools_attach_LinuxVirtualMachine_socket;
-	    Java_sun_tools_attach_LinuxVirtualMachine_read;
-	    Java_sun_tools_attach_LinuxVirtualMachine_write;
+	    Java_sun_tools_attach_VirtualMachineImpl_checkPermissions;
+	    Java_sun_tools_attach_VirtualMachineImpl_close;
+	    Java_sun_tools_attach_VirtualMachineImpl_connect;
+	    Java_sun_tools_attach_VirtualMachineImpl_getLinuxThreadsManager;
+	    Java_sun_tools_attach_VirtualMachineImpl_isLinuxThreads;
+	    Java_sun_tools_attach_VirtualMachineImpl_open;
+	    Java_sun_tools_attach_VirtualMachineImpl_sendQuitTo;
+            Java_sun_tools_attach_VirtualMachineImpl_sendQuitToChildrenOf;
+	    Java_sun_tools_attach_VirtualMachineImpl_socket;
+	    Java_sun_tools_attach_VirtualMachineImpl_read;
+	    Java_sun_tools_attach_VirtualMachineImpl_write;
 	local:
 		*;
 };
diff --git a/jdk/make/mapfiles/libattach/mapfile-solaris b/jdk/make/mapfiles/libattach/mapfile-solaris
index 6e61f754b99..df71490fdb8 100644
--- a/jdk/make/mapfiles/libattach/mapfile-solaris
+++ b/jdk/make/mapfiles/libattach/mapfile-solaris
@@ -27,12 +27,12 @@
 
 SUNWprivate_1.1 {
 	global:
-            Java_sun_tools_attach_SolarisVirtualMachine_checkPermissions;
-            Java_sun_tools_attach_SolarisVirtualMachine_enqueue;
-            Java_sun_tools_attach_SolarisVirtualMachine_open;
-	    Java_sun_tools_attach_SolarisVirtualMachine_close;
-	    Java_sun_tools_attach_SolarisVirtualMachine_read;
-	    Java_sun_tools_attach_SolarisVirtualMachine_sigquit;
+            Java_sun_tools_attach_VirtualMachineImpl_checkPermissions;
+            Java_sun_tools_attach_VirtualMachineImpl_enqueue;
+            Java_sun_tools_attach_VirtualMachineImpl_open;
+	    Java_sun_tools_attach_VirtualMachineImpl_close;
+	    Java_sun_tools_attach_VirtualMachineImpl_read;
+	    Java_sun_tools_attach_VirtualMachineImpl_sigquit;
 	local:
 		*;
 };
diff --git a/jdk/make/mapfiles/libjava/mapfile-vers b/jdk/make/mapfiles/libjava/mapfile-vers
index ca99cc5c03b..3b1d894ff71 100644
--- a/jdk/make/mapfiles/libjava/mapfile-vers
+++ b/jdk/make/mapfiles/libjava/mapfile-vers
@@ -78,13 +78,13 @@ SUNWprivate_1.1 {
 		Java_java_io_FileInputStream_available;
 		Java_java_io_FileInputStream_close0;
 		Java_java_io_FileInputStream_initIDs;
-		Java_java_io_FileInputStream_open;
+		Java_java_io_FileInputStream_open0;
 		Java_java_io_FileInputStream_read0;
 		Java_java_io_FileInputStream_readBytes;
 		Java_java_io_FileInputStream_skip;
 		Java_java_io_FileOutputStream_close0;
 		Java_java_io_FileOutputStream_initIDs;
-		Java_java_io_FileOutputStream_open;
+		Java_java_io_FileOutputStream_open0;
 		Java_java_io_FileOutputStream_write;
 		Java_java_io_FileOutputStream_writeBytes;
 		Java_java_io_ObjectInputStream_bytesToDoubles;
@@ -97,7 +97,7 @@ SUNWprivate_1.1 {
 		Java_java_io_RandomAccessFile_getFilePointer;
 		Java_java_io_RandomAccessFile_initIDs;
 		Java_java_io_RandomAccessFile_length;
-		Java_java_io_RandomAccessFile_open;
+		Java_java_io_RandomAccessFile_open0;
 		Java_java_io_RandomAccessFile_read0;
 		Java_java_io_RandomAccessFile_readBytes;
 		Java_java_io_RandomAccessFile_seek0;
diff --git a/jdk/make/mapfiles/libjava/reorder-sparc b/jdk/make/mapfiles/libjava/reorder-sparc
index 4a5cbf45018..d10037652d1 100644
--- a/jdk/make/mapfiles/libjava/reorder-sparc
+++ b/jdk/make/mapfiles/libjava/reorder-sparc
@@ -44,7 +44,7 @@ text: .text%Java_java_io_UnixFileSystem_initIDs;
 text: .text%Java_java_io_UnixFileSystem_canonicalize;
 text: .text%JNU_GetStringPlatformChars;
 text: .text%JNU_ReleaseStringPlatformChars;
-text: .text%Java_java_io_FileInputStream_open;
+text: .text%Java_java_io_FileInputStream_open0;
 text: .text%fileOpen;
 text: .text%Java_java_io_FileInputStream_readBytes;
 text: .text%readBytes;
diff --git a/jdk/make/mapfiles/libjava/reorder-sparcv9 b/jdk/make/mapfiles/libjava/reorder-sparcv9
index 81cbfcb2410..2609711c21f 100644
--- a/jdk/make/mapfiles/libjava/reorder-sparcv9
+++ b/jdk/make/mapfiles/libjava/reorder-sparcv9
@@ -47,7 +47,7 @@ text: .text%Java_java_io_UnixFileSystem_initIDs;
 text: .text%Java_java_io_UnixFileSystem_canonicalize;
 text: .text%JNU_GetStringPlatformChars;
 text: .text%JNU_ReleaseStringPlatformChars;
-text: .text%Java_java_io_FileInputStream_open;
+text: .text%Java_java_io_FileInputStream_open0;
 text: .text%fileOpen;
 text: .text%Java_java_io_FileInputStream_readBytes;
 text: .text%readBytes;
diff --git a/jdk/make/mapfiles/libjava/reorder-x86 b/jdk/make/mapfiles/libjava/reorder-x86
index 1c971b80eda..b8ea2d43dae 100644
--- a/jdk/make/mapfiles/libjava/reorder-x86
+++ b/jdk/make/mapfiles/libjava/reorder-x86
@@ -57,7 +57,7 @@ text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_load;
 text: .text%Java_java_lang_ClassLoader_00024NativeLibrary_find;
 text: .text%Java_java_lang_Float_floatToIntBits;
 text: .text%Java_java_lang_Double_doubleToLongBits;
-text: .text%Java_java_io_FileInputStream_open;
+text: .text%Java_java_io_FileInputStream_open0;
 text: .text%fileOpen;
 text: .text%Java_java_io_UnixFileSystem_getLength;
 text: .text%Java_java_io_FileInputStream_readBytes;
@@ -90,7 +90,7 @@ text: .text%JNU_NotifyAll;
 text: .text%JNU_CallMethodByName;
 text: .text%JNU_CallMethodByNameV;
 text: .text%Java_java_util_logging_FileHandler_lockFile;
-text: .text%Java_java_io_FileOutputStream_open;
+text: .text%Java_java_io_FileOutputStream_open0;
 text: .text%Java_java_io_UnixFileSystem_createDirectory;
 text: .text%Java_java_io_UnixFileSystem_getLastModifiedTime;
 text: .text%Java_java_util_prefs_FileSystemPreferences_lockFile0;
diff --git a/jdk/make/mapfiles/libnio/mapfile-linux b/jdk/make/mapfiles/libnio/mapfile-linux
index 16f72e43cfa..53555c4763f 100644
--- a/jdk/make/mapfiles/libnio/mapfile-linux
+++ b/jdk/make/mapfiles/libnio/mapfile-linux
@@ -79,6 +79,7 @@ SUNWprivate_1.1 {
 		Java_sun_nio_ch_InheritedChannel_close0;
 		Java_sun_nio_ch_InheritedChannel_dup;
 		Java_sun_nio_ch_InheritedChannel_dup2;
+		Java_sun_nio_ch_InheritedChannel_initIDs;
 		Java_sun_nio_ch_InheritedChannel_open0;
 		Java_sun_nio_ch_InheritedChannel_peerAddress0;
 		Java_sun_nio_ch_InheritedChannel_peerPort0;
diff --git a/jdk/make/mapfiles/libnio/mapfile-macosx b/jdk/make/mapfiles/libnio/mapfile-macosx
index 4dd0dc513e4..d4b6dc5a219 100644
--- a/jdk/make/mapfiles/libnio/mapfile-macosx
+++ b/jdk/make/mapfiles/libnio/mapfile-macosx
@@ -62,6 +62,7 @@ SUNWprivate_1.1 {
 		Java_sun_nio_ch_InheritedChannel_close0;
 		Java_sun_nio_ch_InheritedChannel_dup;
 		Java_sun_nio_ch_InheritedChannel_dup2;
+                Java_sun_nio_ch_InheritedChannel_initIDs;
 		Java_sun_nio_ch_InheritedChannel_open0;
 		Java_sun_nio_ch_InheritedChannel_peerAddress0;
 		Java_sun_nio_ch_InheritedChannel_peerPort0;
diff --git a/jdk/make/mapfiles/libnio/mapfile-solaris b/jdk/make/mapfiles/libnio/mapfile-solaris
index 3933cef7ada..cdbb851bcad 100644
--- a/jdk/make/mapfiles/libnio/mapfile-solaris
+++ b/jdk/make/mapfiles/libnio/mapfile-solaris
@@ -67,6 +67,7 @@ SUNWprivate_1.1 {
 		Java_sun_nio_ch_InheritedChannel_close0;
 		Java_sun_nio_ch_InheritedChannel_dup;
 		Java_sun_nio_ch_InheritedChannel_dup2;
+                Java_sun_nio_ch_InheritedChannel_initIDs;
 		Java_sun_nio_ch_InheritedChannel_open0;
 		Java_sun_nio_ch_InheritedChannel_peerAddress0;
 		Java_sun_nio_ch_InheritedChannel_peerPort0;
diff --git a/jdk/make/profile-includes.txt b/jdk/make/profile-includes.txt
index fe069c37034..d93a8b23936 100644
--- a/jdk/make/profile-includes.txt
+++ b/jdk/make/profile-includes.txt
@@ -168,11 +168,6 @@ FULL_JRE_LIB_FILES := \
     $(OPENJDK_TARGET_CPU_LEGACY_LIB)/$(LIBRARY_PREFIX)t2k$(SHARED_LIBRARY_SUFFIX) \
     $(OPENJDK_TARGET_CPU_LEGACY_LIB)/$(LIBRARY_PREFIX)unpack$(SHARED_LIBRARY_SUFFIX) \
     charsets.jar \
-    cmm/CIEXYZ.pf \
-    cmm/GRAY.pf \
-    cmm/LINEAR_RGB.pf \
-    cmm/PYCC.pf \
-    cmm/sRGB.pf \
     ext/cldrdata.jar \
     ext/dnsns.jar \
     ext/nashorn.jar \
diff --git a/jdk/make/profile-rtjar-includes.txt b/jdk/make/profile-rtjar-includes.txt
index 1e954ad625c..8ab7336fb17 100644
--- a/jdk/make/profile-rtjar-includes.txt
+++ b/jdk/make/profile-rtjar-includes.txt
@@ -201,6 +201,7 @@ FULL_JRE_RTJAR_INCLUDE_PACKAGES := \
     sun/audio \
     sun/awt \
     sun/corba \
+    sun/datatransfer \
     sun/dc \
     sun/font \
     sun/java2d \
diff --git a/jdk/make/src/classes/build/tools/addtorestrictedpkgs/AddToRestrictedPkgs.java b/jdk/make/src/classes/build/tools/addtorestrictedpkgs/AddToRestrictedPkgs.java
deleted file mode 100644
index ee9deb4b75f..00000000000
--- a/jdk/make/src/classes/build/tools/addtorestrictedpkgs/AddToRestrictedPkgs.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-
-package build.tools.addtorestrictedpkgs;
-
-import java.io.*;
-
-/**
- * Adds additional packages to the package.access and package.definition
- * security properties.
- */
-public class AddToRestrictedPkgs {
-
-    private static final String PKG_ACC = "package.access";
-    private static final String PKG_DEF = "package.definition";
-    private static final int PKG_ACC_INDENT = 15;
-    private static final int PKG_DEF_INDENT = 19;
-
-    public static void main(String[] args) throws Exception {
-
-        if (args.length < 3) {
-            System.err.println("Usage: java AddToRestrictedPkgs " +
-                               "[input java.security file name] " +
-                               "[output java.security file name] " +
-                               "[packages ...]");
-            System.exit(1);
-        }
-
-        try (FileReader fr = new FileReader(args[0]);
-             BufferedReader br = new BufferedReader(fr);
-             FileWriter fw = new FileWriter(args[1]);
-             BufferedWriter bw = new BufferedWriter(fw))
-        {
-            // parse the file line-by-line, looking for pkg access properties
-            String line = br.readLine();
-            while (line != null) {
-                if (line.startsWith(PKG_ACC)) {
-                    writePackages(br, bw, line, PKG_ACC_INDENT, args);
-                } else if (line.startsWith(PKG_DEF)) {
-                    writePackages(br, bw, line, PKG_DEF_INDENT, args);
-                } else {
-                    writeLine(bw, line);
-                }
-                line = br.readLine();
-            }
-            bw.flush();
-        }
-    }
-
-    private static void writePackages(BufferedReader br, BufferedWriter bw,
-                                      String line, int numSpaces,
-                                      String[] args) throws IOException {
-        // parse property until EOL, not including line breaks
-        while (line.endsWith("\\")) {
-            writeLine(bw, line);
-            line = br.readLine();
-        }
-        // append comma and line-break to last package
-        writeLine(bw, line + ",\\");
-        // add new packages, one per line
-        for (int i = 2; i < args.length - 1; i++) {
-            indent(bw, numSpaces);
-            writeLine(bw, args[i] + ",\\");
-        }
-        indent(bw, numSpaces);
-        writeLine(bw, args[args.length - 1]);
-    }
-
-    private static void writeLine(BufferedWriter bw, String line)
-        throws IOException
-    {
-        bw.write(line);
-        bw.newLine();
-    }
-
-    private static void indent(BufferedWriter bw, int numSpaces)
-        throws IOException
-    {
-        for (int i = 0; i < numSpaces; i++) {
-            bw.append(' ');
-        }
-    }
-}
diff --git a/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java b/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java
index 33ea34ffa2a..b1f559e7f6f 100644
--- a/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java
+++ b/jdk/make/src/classes/build/tools/cldrconverter/CLDRConverter.java
@@ -431,7 +431,7 @@ public class CLDRConverter {
             allLocales.addAll(metaInfo.get("LocaleNames"));
             allLocales.addAll(metaInfo.get("CalendarData"));
             allLocales.addAll(metaInfo.get("FormatData"));
-            metaInfo.put("All", allLocales);
+            metaInfo.put("AvailableLocales", allLocales);
         }
 
         bundleGenerator.generateMetaInfo(metaInfo);
diff --git a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java
index b905f75290a..27a7b1fbd20 100644
--- a/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java
+++ b/jdk/make/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java
@@ -159,8 +159,10 @@ class ResourceBundleGenerator implements BundleGenerator {
             out.println(CopyrightHeaders.getOpenJDKCopyright());
 
             out.println("package sun.util.cldr;\n\n"
-                      + "import java.util.ListResourceBundle;\n");
-            out.printf("public class %s extends ListResourceBundle {\n", METAINFO_CLASS);
+                      + "import java.util.ListResourceBundle;\n"
+                      + "import sun.util.locale.provider.LocaleProviderAdapter;\n"
+                      + "import sun.util.locale.provider.LocaleDataMetaInfo;\n");
+            out.printf("public class %s extends ListResourceBundle implements LocaleDataMetaInfo {\n", METAINFO_CLASS);
             out.println("    @Override\n" +
                         "    protected final Object[][] getContents() {\n" +
                         "        final Object[][] data = new Object[][] {");
@@ -168,7 +170,15 @@ class ResourceBundleGenerator implements BundleGenerator {
                 out.printf("            { \"%s\",\n", key);
                 out.printf("              \"%s\" },\n", toLocaleList(metaInfo.get(key)));
             }
-            out.println("        };\n        return data;\n    }\n}");
+            out.println("        };\n        return data;\n    }\n\n");
+
+            out.println("    public LocaleProviderAdapter.Type getType() {\n" +
+                        "        return LocaleProviderAdapter.Type.CLDR;\n" +
+                        "    }\n\n");
+
+            out.println("    public String availableLanguageTags(String category) {\n" +
+                        "        return getString(category);\n" +
+                        "    };\n}");
         }
     }
 
diff --git a/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java b/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java
new file mode 100644
index 00000000000..d5c6e14c7b1
--- /dev/null
+++ b/jdk/make/src/classes/build/tools/makejavasecurity/MakeJavaSecurity.java
@@ -0,0 +1,168 @@
+/*
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.  Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package build.tools.makejavasecurity;
+
+import java.io.*;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.*;
+
+/**
+ * Builds the java.security file, including
+ *
+ * 1. Adds additional packages to the package.access and
+ *    package.definition security properties.
+ * 2. Filter out platform-unrelated parts
+ *
+ * In order to easily maintain platform-related entries, every item
+ * (including the last line) in package.access and package.definition
+ * MUST end with ',\'. A blank line MUST exist after the last line.
+ */
+public class MakeJavaSecurity {
+
+    private static final String PKG_ACC = "package.access";
+    private static final String PKG_DEF = "package.definition";
+    private static final int PKG_ACC_INDENT = 15;
+    private static final int PKG_DEF_INDENT = 19;
+
+    public static void main(String[] args) throws Exception {
+
+        if (args.length < 3) {
+            System.err.println("Usage: java MakeJavaSecurity " +
+                               "[input java.security file name] " +
+                               "[output java.security file name] " +
+                               "[openjdk target os] " +
+                               "[more restricted packages file name?]");
+            System.exit(1);
+        }
+
+        // more restricted packages
+        List extraLines;
+        if (args.length == 4) {
+            extraLines = Files.readAllLines(Paths.get(args[3]));
+        } else {
+            extraLines = Collections.emptyList();
+        }
+
+        List lines = new ArrayList<>();
+
+        // read raw java.security and add more restricted packages
+        try (FileReader fr = new FileReader(args[0]);
+                BufferedReader br = new BufferedReader(fr)) {
+            // looking for pkg access properties
+            String line = br.readLine();
+            while (line != null) {
+                if (line.startsWith(PKG_ACC)) {
+                    addPackages(br, lines, line, PKG_ACC_INDENT, extraLines);
+                } else if (line.startsWith(PKG_DEF)) {
+                    addPackages(br, lines, line, PKG_DEF_INDENT, extraLines);
+                } else {
+                    lines.add(line);
+                }
+                line = br.readLine();
+            }
+        }
+
+        // Filter out platform-unrelated ones. We only support
+        // #ifdef, #ifndef, and #endif.
+        int mode = 0;   // 0: out of block, 1: in match, 2: in non-match
+        Iterator iter = lines.iterator();
+        while (iter.hasNext()) {
+            String line = iter.next();
+            if (line.startsWith("#endif")) {
+                mode = 0;
+                iter.remove();
+            } else if (line.startsWith("#ifdef ")) {
+                mode = line.endsWith(args[2])?1:2;
+                iter.remove();
+            } else if (line.startsWith("#ifndef ")) {
+                mode = line.endsWith(args[2])?2:1;
+                iter.remove();
+            } else {
+                if (mode == 2) iter.remove();
+            }
+        }
+
+        // Update .tbd to .1, .2, etc.
+        Map count = new HashMap<>();
+        for (int i=0; i= 0) {
+                String prefix = line.substring(0, index);
+                int n = count.getOrDefault(prefix, 1);
+                count.put(prefix, n+1);
+                lines.set(i, prefix + "." + n + line.substring(index+4));
+            }
+        }
+
+        // Clean up the last line of PKG_ACC and PKG_DEF blocks.
+        // Not really necessary since a blank line follows.
+        boolean inBlock = false;
+        for (int i=0; i lines,
+                                    String line, int numSpaces,
+                                    List args) throws IOException {
+        // parse property until EOL, not including line breaks
+        boolean first = true;
+        while (!line.isEmpty()) {
+            if (!line.startsWith("#")) {
+                if (!line.endsWith(",\\") ||
+                        (!first && line.contains("="))) {
+                    throw new IOException("Invalid line: " + line);
+                }
+            }
+            lines.add(line);
+            line = br.readLine();
+            first = false;
+        }
+        // add new packages, one per line
+        for (String arg: args) {
+            if (arg.startsWith("#")) {
+                lines.add(arg);
+            } else {
+                lines.add(String.format("%"+numSpaces+"s", "") + arg + ",\\");
+            }
+        }
+        lines.add(line);
+    }
+}
diff --git a/jdk/make/src/classes/build/tools/module/GenerateModulesXml.java b/jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java
similarity index 90%
rename from jdk/make/src/classes/build/tools/module/GenerateModulesXml.java
rename to jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java
index c2fdf4ae9d1..43ba458f326 100644
--- a/jdk/make/src/classes/build/tools/module/GenerateModulesXml.java
+++ b/jdk/make/src/classes/build/tools/module/GenJdepsModulesXml.java
@@ -25,6 +25,7 @@
 
 package build.tools.module;
 
+import java.io.BufferedInputStream;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
@@ -49,47 +50,56 @@ import javax.xml.stream.events.Attribute;
 import javax.xml.stream.events.XMLEvent;
 
 /**
- * This tool is used to generate com/sun/tools/jdeps/resources/modules.xml
- * for jdeps to analyze dependencies and enforce module boundaries.
+ * GenJdepsModulesXml augments the input modules.xml file(s)
+ * to include the module membership from the given path to
+ * the JDK exploded image.  The output file is used by jdeps
+ * to analyze dependencies and enforce module boundaries.
  *
- * $ java build.tools.module.GenerateModulesXml \
- *        com/sun/tools/jdeps/resources/modules.xml $OUTPUTDIR/modules
+ * The input modules.xml file defines the modular structure of
+ * the JDK as described in JEP 200: The Modular JDK
+ * (http://openjdk.java.net/jeps/200).
  *
- * This will generate modules.xml as jdeps resources that extend
- * the metadata to include module membership (jdeps needs the
- * membership information to determine which module a type belongs to.)
+ * $ java build.tools.module.GenJdepsModulesXml \
+ *        -o com/sun/tools/jdeps/resources/modules.xml \
+ *        -mp $OUTPUTDIR/modules \
+ *        top/modules.xml
  */
-public final class GenerateModulesXml {
+public final class GenJdepsModulesXml {
     private final static String USAGE =
-        "Usage: GenerateModulesXml  build/modules";
+        "Usage: GenJdepsModulesXml -o  -mp build/modules path-to-modules-xml";
 
     public static void main(String[] args) throws Exception {
-        if (args.length < 2) {
+        Path outfile = null;
+        Path modulepath = null;
+        int i = 0;
+        while (i < args.length) {
+            String arg = args[i];
+            if (arg.equals("-o")) {
+                outfile = Paths.get(args[i+1]);
+                i = i+2;
+            } else if (arg.equals("-mp")) {
+                modulepath = Paths.get(args[i+1]);
+                i = i+2;
+                if (!Files.isDirectory(modulepath)) {
+                    System.err.println(modulepath + " is not a directory");
+                    System.exit(1);
+                }
+            } else {
+                break;
+            }
+        }
+        if (outfile == null || modulepath == null || i >= args.length) {
             System.err.println(USAGE);
             System.exit(-1);
         }
 
-        Path outfile = Paths.get(args[0]);
-        Path modulepath = Paths.get(args[1]);
-
-        if (!Files.isDirectory(modulepath)) {
-            System.err.println(modulepath + " is not a directory");
-            System.exit(1);
-        }
-        GenerateModulesXml gentool =
-            new GenerateModulesXml(modulepath);
-        Set modules;
-        try (InputStream in = GenerateModulesXml.class.getResourceAsStream("modules.xml")) {
-            modules = gentool.load(in);
-        }
-
-        InputStream in = GenerateModulesXml.class.getResourceAsStream("closed/modules.xml");
-        if (in != null) {
-            try {
+        GenJdepsModulesXml gentool = new GenJdepsModulesXml(modulepath);
+        Set modules = new HashSet<>();
+        for (; i < args.length; i++) {
+            Path p = Paths.get(args[i]);
+            try (InputStream in = new BufferedInputStream(Files.newInputStream(p))) {
                 Set mods = gentool.load(in);
                 modules.addAll(mods);
-            } finally {
-                in.close();
             }
         }
 
@@ -98,7 +108,7 @@ public final class GenerateModulesXml {
     }
 
     final Path modulepath;
-    public GenerateModulesXml(Path modulepath) {
+    public GenJdepsModulesXml(Path modulepath) {
         this.modulepath = modulepath;
     }
 
@@ -275,7 +285,7 @@ public final class GenerateModulesXml {
             m.exports().keySet().stream()
                        .filter(pn -> m.exports().get(pn).isEmpty())
                        .sorted()
-                       .forEach(pn -> GenerateModulesXml.this.writeExportElement(xtw, pn, depth+1));
+                       .forEach(pn -> writeExportElement(xtw, pn, depth+1));
             m.exports().entrySet().stream()
                        .filter(e -> !e.getValue().isEmpty())
                        .sorted(Map.Entry.comparingByKey())
diff --git a/jdk/src/demo/share/java2d/J2DBench/Makefile b/jdk/src/demo/share/java2d/J2DBench/Makefile
index ece84b7ea66..6082d3330f5 100644
--- a/jdk/src/demo/share/java2d/J2DBench/Makefile
+++ b/jdk/src/demo/share/java2d/J2DBench/Makefile
@@ -72,6 +72,7 @@ J2DANALYZER_CLASSES = \
 
 J2DBENCH_RESOURCES = \
 	$(CLASSES)/j2dbench/tests/iio/images \
+	$(CLASSES)/j2dbench/tests/cmm/images \
 	$(CLASSES)/j2dbench/tests/text/textdata
 
 SCM_DIRs = .hg .svn CVS RCS SCCS Codemgr_wsdata deleted_files
@@ -101,6 +102,10 @@ $(CLASSES)/j2dbench/tests/text/textdata: $(RESOURCES)/textdata
 	cp -r $< $@
 	cd $@ && rm -rf $(SCM_DIRs)
 
+$(CLASSES)/j2dbench/tests/cmm/images: $(RESOURCES)/cmm_images
+	cp -r $< $@
+	cd $@ && rm -rf $(SCM_DIRs)
+
 $(CLASSES)/j2dbench.manifest:
 	echo "Main-Class: j2dbench.J2DBench" > $@
 
@@ -115,7 +120,7 @@ $(CLASSES):
 mkdirs: $(DIST) $(CLASSES)
 
 $(CLASSES)/j2dbench/%.class: $(SOURCEPATH)/j2dbench/%.java
-	javac -source 1.2 -target 1.2 -d $(CLASSES) -sourcepath $(SOURCEPATH) $<
+	javac -g:none -source 1.6 -target 1.6 -d $(CLASSES) -sourcepath $(SOURCEPATH) $<
 
 clean:
 	rm -rf $(CLASSES)
diff --git a/jdk/src/demo/share/java2d/J2DBench/README b/jdk/src/demo/share/java2d/J2DBench/README
index c3d5a36a53f..09e214ee203 100644
--- a/jdk/src/demo/share/java2d/J2DBench/README
+++ b/jdk/src/demo/share/java2d/J2DBench/README
@@ -19,10 +19,9 @@ from the results files generated by the J2DBench runs.
 Minimum requirements
 -----------------------------------------------------------------------
 
-The benchmark requires at least jdk1.4 to compile and
-at least jdk1.2** to run.
-
-** Note: the goal is to make the benchmark run on 1.1.x as well.
+The benchmark requires at least jdk1.4 to compile and run. Note that
+source/target is set to 1.6 in the makefile and build.xml, because of
+support in jdk 9 compiler.
 
 -----------------------------------------------------------------------
 How To Compile
@@ -125,7 +124,7 @@ choosing the options and benchmarks to run.
 
 After the options file is created, start J2DBench in batch mode to run
 the benchmarks for the default pipeline:
-#> java -jar dest/J2DBench.jar -batch -loadopts options/default.opt \
+#> java -jar dist/J2DBench.jar -batch -loadopts options/default.opt \
      -saveres default.res -title "Rendering - Default ppl" \
      -desc "Rendering tests with the default pipeline"
 
@@ -136,13 +135,13 @@ file and save the result in default.res file.
 "Run Tests" in the J2DBench dialog)
 
 Now run the benchmark with opengl pipeline:
-#> java -Dsun.java2d.opengl=True -jar dest/J2DBench.jar -batch \
+#> java -Dsun.java2d.opengl=True -jar dist/J2DBench.jar -batch \
      -loadopts options/default.opt \
      -saveres opengl.res -title "Rendering - OpenGL" \
      -desc "Rendering tests with OpenGL pipeline"
 
 Now let's analyze the results using J2DAnalyzer:
-#> java -jar dest/J2DAnalyzer.jar default.res opengl.res
+#> java -jar dist/J2DAnalyzer.jar default.res opengl.res
 
 Note that you can compare more than two sets of results, see
 J2DAnalyzer's help page.
diff --git a/jdk/src/demo/share/java2d/J2DBench/build.xml b/jdk/src/demo/share/java2d/J2DBench/build.xml
index c2af9ec6007..3ae3bc186aa 100644
--- a/jdk/src/demo/share/java2d/J2DBench/build.xml
+++ b/jdk/src/demo/share/java2d/J2DBench/build.xml
@@ -49,7 +49,7 @@
   
     
-    
+    
   
 
    arguments,
-                        InputListener input,
-                        OutputListener output,
-                        OutputListener error,
-                        OutputListener diagnostics) {
-        this(runtime, generalGetVM(diagnostics, connector, arguments),
-             input, output, error, diagnostics);
-    }
-
-    private ChildSession(ExecutionManager runtime,
-                        VirtualMachine vm,
-                        InputListener input,
-                        OutputListener output,
-                        OutputListener error,
-                        OutputListener diagnostics) {
-        super(vm, runtime, diagnostics);
-        this.input = input;
-        this.output = output;
-        this.error = error;
-    }
-
-    @Override
-    public boolean attach() {
-
-        if (!connectToVMProcess()) {
-            diagnostics.putString("Could not launch VM");
-            return false;
-        }
-
-        /*
-         * Create a Thread that will retrieve and display any output.
-         * Needs to be high priority, else debugger may exit before
-         * it can be displayed.
-         */
-
-        //### Rename InputWriter and OutputReader classes
-        //### Thread priorities cribbed from ttydebug.  Think about them.
-
-        OutputReader outputReader =
-            new OutputReader("output reader", "output",
-                             out, output, diagnostics);
-        outputReader.setPriority(Thread.MAX_PRIORITY-1);
-        outputReader.start();
-
-        OutputReader errorReader =
-            new OutputReader("error reader", "error",
-                             err, error, diagnostics);
-        errorReader.setPriority(Thread.MAX_PRIORITY-1);
-        errorReader.start();
-
-        InputWriter inputWriter =
-            new InputWriter("input writer", in, input);
-        inputWriter.setPriority(Thread.MAX_PRIORITY-1);
-        inputWriter.start();
-
-        if (!super.attach()) {
-            if (process != null) {
-                process.destroy();
-                process = null;
-            }
-            return false;
-        }
-
-        //### debug
-        //System.out.println("IO after attach: "+ inputWriter + " " + outputReader + " "+ errorReader);
-
-        return true;
-    }
-
-    @Override
-    public void detach() {
-
-        //### debug
-        //System.out.println("IO before detach: "+ inputWriter + " " + outputReader + " "+ errorReader);
-
-        super.detach();
-
-        /*
-        inputWriter.quit();
-        outputReader.quit();
-        errorReader.quit();
-        */
-
-        if (process != null) {
-            process.destroy();
-            process = null;
-        }
-
-    }
-
-    /**
-     * Launch child java interpreter, return host:port
-     */
-
-    static private void dumpStream(OutputListener diagnostics,
-                                   InputStream stream) throws IOException {
-        BufferedReader in =
-            new BufferedReader(new InputStreamReader(stream));
-        String line;
-        while ((line = in.readLine()) != null) {
-            diagnostics.putString(line);
-        }
-    }
-
-    static private void dumpFailedLaunchInfo(OutputListener diagnostics,
-                                             Process process) {
-        try {
-            dumpStream(diagnostics, process.getErrorStream());
-            dumpStream(diagnostics, process.getInputStream());
-        } catch (IOException e) {
-            diagnostics.putString("Unable to display process output: " +
-                                  e.getMessage());
-        }
-    }
-
-    static private VirtualMachine getVM(OutputListener diagnostics,
-                                        String userVMArgs,
-                                        String cmdLine) {
-        VirtualMachineManager manager = Bootstrap.virtualMachineManager();
-        LaunchingConnector connector = manager.defaultConnector();
-        Map arguments = connector.defaultArguments();
-        arguments.get("options").setValue(userVMArgs);
-        arguments.get("main").setValue(cmdLine);
-        return generalGetVM(diagnostics, connector, arguments);
-    }
-
-    static private VirtualMachine generalGetVM(OutputListener diagnostics,
-                                               LaunchingConnector connector,
-                                               Map arguments) {
-        VirtualMachine vm = null;
-        try {
-            diagnostics.putString("Starting child.");
-            vm = connector.launch(arguments);
-        } catch (IOException ioe) {
-            diagnostics.putString("Unable to start child: " + ioe.getMessage());
-        } catch (IllegalConnectorArgumentsException icae) {
-            diagnostics.putString("Unable to start child: " + icae.getMessage());
-        } catch (VMStartException vmse) {
-            diagnostics.putString("Unable to start child: " + vmse.getMessage() + '\n');
-            dumpFailedLaunchInfo(diagnostics, vmse.process());
-        }
-        return vm;
-    }
-
-    private boolean connectToVMProcess() {
-        if (vm == null) {
-            return false;
-        }
-        process = vm.process();
-        in = new PrintWriter(new OutputStreamWriter(process.getOutputStream()));
-        //### Note small buffer sizes!
-        out = new BufferedReader(new InputStreamReader(process.getInputStream()), 1);
-        err = new BufferedReader(new InputStreamReader(process.getErrorStream()), 1);
-        return true;
-    }
-
-    /**
-     *  Threads to handle application input/output.
-     */
-
-    private static class OutputReader extends Thread {
-
-        private String streamName;
-        private BufferedReader stream;
-        private OutputListener output;
-        private OutputListener diagnostics;
-        private boolean running = true;
-        private char[] buffer = new char[512];
-
-        OutputReader(String threadName,
-                     String streamName,
-                     BufferedReader stream,
-                     OutputListener output,
-                     OutputListener diagnostics) {
-            super(threadName);
-            this.streamName = streamName;
-            this.stream = stream;
-            this.output = output;
-            this.diagnostics = diagnostics;
-        }
-
-        @Override
-        public void run() {
-            try {
-                int count;
-                while (running && (count = stream.read(buffer, 0, 512)) != -1) {
-                    if (count > 0) {
-                        // Run in Swing event dispatcher thread.
-                        final String chars = new String(buffer, 0, count);
-                        SwingUtilities.invokeLater(new Runnable() {
-                            @Override
-                            public void run() {
-                                output.putString(chars);
-                            }
-                        });
-                    }
-                    //### Should we sleep briefly here?
-                }
-            } catch (IOException e) {
-                // Run in Swing event dispatcher thread.
-                SwingUtilities.invokeLater(new Runnable() {
-                    @Override
-                    public void run() {
-                        diagnostics.putString("IO error reading " +
-                                              streamName +
-                                              " stream of child java interpreter");
-                    }
-                });
-            }
-        }
-    }
-
-    private static class InputWriter extends Thread {
-
-        private PrintWriter stream;
-        private InputListener input;
-        private boolean running = true;
-
-        InputWriter(String threadName,
-                    PrintWriter stream,
-                    InputListener input) {
-            super(threadName);
-            this.stream = stream;
-            this.input = input;
-        }
-
-        @Override
-        public void run() {
-            String line;
-            while (running) {
-                line = input.getLine();
-                stream.println(line);
-                // Should not be needed for println above!
-                stream.flush();
-            }
-        }
-    }
-
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpec.java
deleted file mode 100644
index 0ea58fb3ebd..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpec.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.*;
-import com.sun.jdi.request.EventRequest;
-
-abstract public class EventRequestSpec {
-
-    static final int STATUS_UNRESOLVED = 1;
-    static final int STATUS_RESOLVED = 2;
-    static final int STATUS_ERROR = 3;
-
-    static final Object specPropertyKey = "spec";
-
-    final EventRequestSpecList specs;
-    final ReferenceTypeSpec refSpec;
-    EventRequest request = null;
-
-    int status = STATUS_UNRESOLVED;
-
-    EventRequestSpec(EventRequestSpecList specs, ReferenceTypeSpec refSpec) {
-        this.specs = specs;
-        this.refSpec = refSpec;
-    }
-
-    void setRequest(EventRequest request) {
-        this.request = request;
-        request.putProperty(specPropertyKey, this);
-        request.enable();
-    }
-
-    /**
-     * The 'refType' is known to match.
-     */
-    abstract void resolve(ReferenceType refType) throws Exception;
-
-    abstract void notifySet(SpecListener listener, SpecEvent evt);
-    abstract void notifyDeferred(SpecListener listener, SpecEvent evt);
-    abstract void notifyResolved(SpecListener listener, SpecEvent evt);
-    abstract void notifyDeleted(SpecListener listener, SpecEvent evt);
-    abstract void notifyError(SpecListener listener, SpecErrorEvent evt);
-
-    /**
-     * The 'refType' is known to match.
-     */
-    void resolveNotify(ReferenceType refType) {
-        try {
-            resolve(refType);
-            status = STATUS_RESOLVED;
-            specs.notifyResolved(this);
-        } catch(Exception exc) {
-            status = STATUS_ERROR;
-            specs.notifyError(this, exc);
-        }
-    }
-
-    /**
-     * See if 'refType' matches and resolve.
-     */
-    void attemptResolve(ReferenceType refType) {
-        if (!isResolved() && refSpec.matches(refType)) {
-            resolveNotify(refType);
-        }
-    }
-
-    void attemptImmediateResolve(VirtualMachine vm) {
-        // try to resolve immediately
-        for (ReferenceType refType : vm.allClasses()) {
-            if (refSpec.matches(refType)) {
-                try {
-                    resolve(refType);
-                    status = STATUS_RESOLVED;
-                    specs.notifySet(this);
-                } catch(Exception exc) {
-                    status = STATUS_ERROR;
-                    specs.notifyError(this, exc);
-                }
-                return;
-            }
-        }
-        specs.notifyDeferred(this);
-    }
-
-    public EventRequest getEventRequest() {
-        return request;
-    }
-
-    /**
-     * @return true if this spec has been resolved.
-     */
-    public boolean isResolved() {
-        return status == STATUS_RESOLVED;
-    }
-
-    /**
-     * @return true if this spec has not yet been resolved.
-     */
-    public boolean isUnresolved() {
-        return status == STATUS_UNRESOLVED;
-    }
-
-    /**
-     * @return true if this spec is unresolvable due to error.
-     */
-    public boolean isErroneous() {
-        return status == STATUS_ERROR;
-    }
-
-    public String getStatusString() {
-        switch (status) {
-            case STATUS_RESOLVED:
-                return "resolved";
-            case STATUS_UNRESOLVED:
-                return "deferred";
-            case STATUS_ERROR:
-                return "erroneous";
-        }
-        return "unknown";
-    }
-
-    boolean isJavaIdentifier(String s) {
-        return Utils.isJavaIdentifier(s);
-    }
-
-    public String errorMessageFor(Exception e) {
-        if (e instanceof IllegalArgumentException) {
-            return ("Invalid command syntax");
-        } else if (e instanceof RuntimeException) {
-            // A runtime exception that we were not expecting
-            throw (RuntimeException)e;
-        } else {
-            return ("Internal error; unable to set" + this);
-        }
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpecList.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpecList.java
deleted file mode 100644
index 17c001483c7..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/EventRequestSpecList.java
+++ /dev/null
@@ -1,187 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.*;
-import com.sun.jdi.request.*;
-
-import java.util.*;
-
-class EventRequestSpecList {
-
-    // all specs
-    private List eventRequestSpecs = Collections.synchronizedList(
-                                                  new ArrayList());
-
-    final ExecutionManager runtime;
-
-    EventRequestSpecList(ExecutionManager runtime) {
-        this.runtime = runtime;
-    }
-
-    /**
-     * Resolve all deferred eventRequests waiting for 'refType'.
-     */
-    void resolve(ReferenceType refType) {
-        synchronized(eventRequestSpecs) {
-            for (EventRequestSpec spec : eventRequestSpecs) {
-                spec.attemptResolve(refType);
-             }
-        }
-    }
-
-    void install(EventRequestSpec ers, VirtualMachine vm) {
-        synchronized (eventRequestSpecs) {
-            eventRequestSpecs.add(ers);
-        }
-        if (vm != null) {
-            ers.attemptImmediateResolve(vm);
-        }
-    }
-
-    BreakpointSpec
-    createClassLineBreakpoint(String classPattern, int line) {
-        ReferenceTypeSpec refSpec =
-            new PatternReferenceTypeSpec(classPattern);
-        return new LineBreakpointSpec(this, refSpec, line);
-    }
-
-    BreakpointSpec
-    createSourceLineBreakpoint(String sourceName, int line) {
-        ReferenceTypeSpec refSpec =
-            new SourceNameReferenceTypeSpec(sourceName, line);
-        return new LineBreakpointSpec(this, refSpec, line);
-    }
-
-    BreakpointSpec
-    createMethodBreakpoint(String classPattern,
-                           String methodId, List methodArgs) {
-        ReferenceTypeSpec refSpec =
-            new PatternReferenceTypeSpec(classPattern);
-        return new MethodBreakpointSpec(this, refSpec,
-                                        methodId, methodArgs);
-    }
-
-    ExceptionSpec
-    createExceptionIntercept(String classPattern,
-                             boolean notifyCaught,
-                             boolean notifyUncaught) {
-        ReferenceTypeSpec refSpec =
-            new PatternReferenceTypeSpec(classPattern);
-        return new ExceptionSpec(this, refSpec,
-                                 notifyCaught, notifyUncaught);
-    }
-
-    AccessWatchpointSpec
-    createAccessWatchpoint(String classPattern, String fieldId) {
-        ReferenceTypeSpec refSpec =
-            new PatternReferenceTypeSpec(classPattern);
-        return new AccessWatchpointSpec(this, refSpec, fieldId);
-    }
-
-    ModificationWatchpointSpec
-    createModificationWatchpoint(String classPattern, String fieldId) {
-        ReferenceTypeSpec refSpec =
-            new PatternReferenceTypeSpec(classPattern);
-        return new ModificationWatchpointSpec(this, refSpec, fieldId);
-    }
-
-    void delete(EventRequestSpec ers) {
-        EventRequest request = ers.getEventRequest();
-        synchronized (eventRequestSpecs) {
-            eventRequestSpecs.remove(ers);
-        }
-        if (request != null) {
-            request.virtualMachine().eventRequestManager()
-                .deleteEventRequest(request);
-        }
-        notifyDeleted(ers);
-        //### notify delete - here?
-    }
-
-    List eventRequestSpecs() {
-        // We need to make a copy to avoid synchronization problems
-        synchronized (eventRequestSpecs) {
-            return new ArrayList(eventRequestSpecs);
-        }
-    }
-
-    // --------  notify routines --------------------
-
-    @SuppressWarnings("unchecked")
-    private Vector specListeners() {
-        return (Vector)runtime.specListeners.clone();
-    }
-
-    void notifySet(EventRequestSpec spec) {
-        Vector l = specListeners();
-        SpecEvent evt = new SpecEvent(spec);
-        for (int i = 0; i < l.size(); i++) {
-            spec.notifySet(l.elementAt(i), evt);
-        }
-    }
-
-    void notifyDeferred(EventRequestSpec spec) {
-        Vector l = specListeners();
-        SpecEvent evt = new SpecEvent(spec);
-        for (int i = 0; i < l.size(); i++) {
-            spec.notifyDeferred(l.elementAt(i), evt);
-        }
-    }
-
-    void notifyDeleted(EventRequestSpec spec) {
-        Vector l = specListeners();
-        SpecEvent evt = new SpecEvent(spec);
-        for (int i = 0; i < l.size(); i++) {
-            spec.notifyDeleted(l.elementAt(i), evt);
-        }
-    }
-
-    void notifyResolved(EventRequestSpec spec) {
-        Vector l = specListeners();
-        SpecEvent evt = new SpecEvent(spec);
-        for (int i = 0; i < l.size(); i++) {
-            spec.notifyResolved(l.elementAt(i), evt);
-        }
-    }
-
-    void notifyError(EventRequestSpec spec, Exception exc) {
-        Vector l = specListeners();
-        SpecErrorEvent evt = new SpecErrorEvent(spec, exc);
-        for (int i = 0; i < l.size(); i++) {
-            spec.notifyError(l.elementAt(i), evt);
-        }
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExceptionSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExceptionSpec.java
deleted file mode 100644
index df87688152c..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExceptionSpec.java
+++ /dev/null
@@ -1,109 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.ReferenceType;
-
-public class ExceptionSpec extends EventRequestSpec {
-
-    boolean notifyCaught;
-    boolean notifyUncaught;
-
-    ExceptionSpec(EventRequestSpecList specs, ReferenceTypeSpec refSpec,
-                  boolean notifyCaught, boolean notifyUncaught)
-    {
-        super(specs, refSpec);
-        this.notifyCaught = notifyCaught;
-        this.notifyUncaught = notifyUncaught;
-    }
-
-    @Override
-    void notifySet(SpecListener listener, SpecEvent evt) {
-        listener.exceptionInterceptSet(evt);
-    }
-
-    @Override
-    void notifyDeferred(SpecListener listener, SpecEvent evt) {
-        listener.exceptionInterceptDeferred(evt);
-    }
-
-    @Override
-    void notifyResolved(SpecListener listener, SpecEvent evt) {
-        listener.exceptionInterceptResolved(evt);
-    }
-
-    @Override
-    void notifyDeleted(SpecListener listener, SpecEvent evt) {
-        listener.exceptionInterceptDeleted(evt);
-    }
-
-    @Override
-    void notifyError(SpecListener listener, SpecErrorEvent evt) {
-        listener.exceptionInterceptError(evt);
-    }
-
-    /**
-     * The 'refType' is known to match.
-     */
-    @Override
-    void resolve(ReferenceType refType) {
-        setRequest(refType.virtualMachine().eventRequestManager()
-                   .createExceptionRequest(refType,
-                                           notifyCaught, notifyUncaught));
-    }
-
-    @Override
-    public int hashCode() {
-        return refSpec.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof ExceptionSpec) {
-            ExceptionSpec es = (ExceptionSpec)obj;
-
-            return refSpec.equals(es.refSpec);
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("exception catch ");
-        sb.append(refSpec.toString());
-        return sb.toString();
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExecutionManager.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExecutionManager.java
deleted file mode 100644
index b5bc053a3c3..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ExecutionManager.java
+++ /dev/null
@@ -1,824 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.*;
-import com.sun.jdi.request.*;
-import com.sun.jdi.connect.*;
-import com.sun.tools.example.debug.expr.ExpressionParser;
-import com.sun.tools.example.debug.expr.ParseException;
-
-import java.io.*;
-import java.util.*;
-
-import com.sun.tools.example.debug.event.*;
-
-import javax.swing.SwingUtilities;
-
-/**
- * Move this towards being only state and functionality
- * that spans across Sessions (and thus VMs).
- */
-public class ExecutionManager {
-
-    private Session session;
-
-    /**
-     * Get/set JDI trace mode.
-     */
-    int traceMode = VirtualMachine.TRACE_NONE;
-
-  //////////////////    Listener registration    //////////////////
-
-  // Session Listeners
-
-    ArrayList sessionListeners = new ArrayList();
-
-    public void addSessionListener(SessionListener listener) {
-        sessionListeners.add(listener);
-    }
-
-    public void removeSessionListener(SessionListener listener) {
-        sessionListeners.remove(listener);
-    }
-
-  // Spec Listeners
-
-  ArrayList specListeners = new ArrayList();
-
-    public void addSpecListener(SpecListener cl) {
-        specListeners.add(cl);
-    }
-
-    public void removeSpecListener(SpecListener cl) {
-        specListeners.remove(cl);
-    }
-
-    // JDI Listeners
-
-    ArrayList jdiListeners = new ArrayList();
-
-    /**
-     * Adds a JDIListener
-     */
-    public void addJDIListener(JDIListener jl) {
-        jdiListeners.add(jl);
-    }
-
-    /**
-     * Adds a JDIListener - at the specified position
-     */
-    public void addJDIListener(int index, JDIListener jl) {
-        jdiListeners.add(index, jl);
-    }
-
-    /**
-     * Removes a JDIListener
-     */
-    public void removeJDIListener(JDIListener jl) {
-        jdiListeners.remove(jl);
-    }
-
-  // App Echo Listeners
-
-    private ArrayList appEchoListeners = new ArrayList();
-
-    public void addApplicationEchoListener(OutputListener l) {
-        appEchoListeners.add(l);
-    }
-
-    public void removeApplicationEchoListener(OutputListener l) {
-        appEchoListeners.remove(l);
-    }
-
-  // App Output Listeners
-
-    private ArrayList appOutputListeners = new ArrayList();
-
-    public void addApplicationOutputListener(OutputListener l) {
-        appOutputListeners.add(l);
-    }
-
-    public void removeApplicationOutputListener(OutputListener l) {
-        appOutputListeners.remove(l);
-    }
-
-  // App Error Listeners
-
-    private ArrayList appErrorListeners = new ArrayList();
-
-    public void addApplicationErrorListener(OutputListener l) {
-        appErrorListeners.add(l);
-    }
-
-    public void removeApplicationErrorListener(OutputListener l) {
-        appErrorListeners.remove(l);
-    }
-
-  // Diagnostic Listeners
-
-    private ArrayList diagnosticsListeners = new ArrayList();
-
-    public void addDiagnosticsListener(OutputListener l) {
-        diagnosticsListeners.add(l);
-    }
-
-    public void removeDiagnosticsListener(OutputListener l) {
-        diagnosticsListeners.remove(l);
-    }
-
-  ///////////    End Listener Registration    //////////////
-
-    //### We probably don't want this public
-    public VirtualMachine vm() {
-        return session == null ? null : session.vm;
-    }
-
-    void ensureActiveSession() throws NoSessionException {
-        if (session == null) {
-         throw new NoSessionException();
-      }
-    }
-
-    public EventRequestManager eventRequestManager() {
-        return vm() == null ? null : vm().eventRequestManager();
-    }
-
-    /**
-     * Get JDI trace mode.
-     */
-    public int getTraceMode(int mode) {
-        return traceMode;
-    }
-
-    /**
-     * Set JDI trace mode.
-     */
-    public void setTraceMode(int mode) {
-        traceMode = mode;
-        if (session != null) {
-            session.setTraceMode(mode);
-        }
-    }
-
-    /**
-     * Determine if VM is interrupted, i.e, present and not running.
-     */
-    public boolean isInterrupted() /* should: throws NoSessionException */ {
-//      ensureActiveSession();
-        return session.interrupted;
-    }
-
-    /**
-     * Return a list of ReferenceType objects for all
-     * currently loaded classes and interfaces.
-     * Array types are not returned.
-     */
-    public List allClasses() throws NoSessionException {
-        ensureActiveSession();
-        return vm().allClasses();
-    }
-
-    /**
-     * Return a ReferenceType object for the currently
-     * loaded class or interface whose fully-qualified
-     * class name is specified, else return null if there
-     * is none.
-     *
-     * In general, we must return a list of types, because
-     * multiple class loaders could have loaded a class
-     * with the same fully-qualified name.
-     */
-    public List findClassesByName(String name) throws NoSessionException {
-        ensureActiveSession();
-        return vm().classesByName(name);
-    }
-
-    /**
-     * Return a list of ReferenceType objects for all
-     * currently loaded classes and interfaces whose name
-     * matches the given pattern.  The pattern syntax is
-     * open to some future revision, but currently consists
-     * of a fully-qualified class name in which the first
-     * component may optionally be a "*" character, designating
-     * an arbitrary prefix.
-     */
-    public List findClassesMatchingPattern(String pattern)
-                                                throws NoSessionException {
-        ensureActiveSession();
-        List result = new ArrayList();  //### Is default size OK?
-        if (pattern.startsWith("*.")) {
-            // Wildcard matches any leading package name.
-            pattern = pattern.substring(1);
-            for (ReferenceType type : vm().allClasses()) {
-                if (type.name().endsWith(pattern)) {
-                    result.add(type);
-                }
-            }
-            return result;
-        } else {
-            // It's a class name.
-            return vm().classesByName(pattern);
-        }
-    }
-
-    /*
-     * Return a list of ThreadReference objects corresponding
-     * to the threads that are currently active in the VM.
-     * A thread is removed from the list just before the
-     * thread terminates.
-     */
-
-    public List allThreads() throws NoSessionException {
-        ensureActiveSession();
-        return vm().allThreads();
-    }
-
-    /*
-     * Return a list of ThreadGroupReference objects corresponding
-     * to the top-level threadgroups that are currently active in the VM.
-     * Note that a thread group may be empty, or contain no threads as
-     * descendents.
-     */
-
-    public List topLevelThreadGroups() throws NoSessionException {
-        ensureActiveSession();
-        return vm().topLevelThreadGroups();
-    }
-
-    /*
-     * Return the system threadgroup.
-     */
-
-    public ThreadGroupReference systemThreadGroup()
-                                                throws NoSessionException {
-        ensureActiveSession();
-        return vm().topLevelThreadGroups().get(0);
-    }
-
-    /*
-     * Evaluate an expression.
-     */
-
-    public Value evaluate(final StackFrame f, String expr)
-        throws ParseException,
-                                            InvocationException,
-                                            InvalidTypeException,
-                                            ClassNotLoadedException,
-                                            NoSessionException,
-                                            IncompatibleThreadStateException {
-        ExpressionParser.GetFrame frameGetter = null;
-        ensureActiveSession();
-        if (f != null) {
-            frameGetter = new ExpressionParser.GetFrame() {
-                @Override
-                public StackFrame get() /* throws IncompatibleThreadStateException */ {
-                    return f;
-                }
-            };
-        }
-        return ExpressionParser.evaluate(expr, vm(), frameGetter);
-    }
-
-
-    /*
-     * Start a new VM.
-     */
-
-    public void run(boolean suspended,
-                    String vmArgs,
-                    String className,
-                    String args) throws VMLaunchFailureException {
-
-        endSession();
-
-        //### Set a breakpoint on 'main' method.
-        //### Would be cleaner if we could just bring up VM already suspended.
-        if (suspended) {
-            //### Set breakpoint at 'main(java.lang.String[])'.
-            List argList = new ArrayList(1);
-            argList.add("java.lang.String[]");
-            createMethodBreakpoint(className, "main", argList);
-        }
-
-        String cmdLine = className + " " + args;
-
-        startSession(new ChildSession(this, vmArgs, cmdLine,
-                                      appInput, appOutput, appError,
-                                      diagnostics));
-    }
-
-    /*
-     * Attach to an existing VM.
-     */
-    public void attach(String portName) throws VMLaunchFailureException {
-        endSession();
-
-        //### Changes made here for connectors have broken the
-        //### the 'Session' abstraction.  The 'Session.attach()'
-        //### method is intended to encapsulate all of the various
-        //### ways in which session start-up can fail. (maddox 12/18/98)
-
-        /*
-         * Now that attaches and launches both go through Connectors,
-         * it may be worth creating a new subclass of Session for
-         * attach sessions.
-         */
-        VirtualMachineManager mgr = Bootstrap.virtualMachineManager();
-        AttachingConnector connector = mgr.attachingConnectors().get(0);
-        Map arguments = connector.defaultArguments();
-        arguments.get("port").setValue(portName);
-
-        Session newSession = internalAttach(connector, arguments);
-        if (newSession != null) {
-            startSession(newSession);
-        }
-    }
-
-    private Session internalAttach(AttachingConnector connector,
-                                   Map arguments) {
-        try {
-            VirtualMachine vm = connector.attach(arguments);
-            return new Session(vm, this, diagnostics);
-        } catch (IOException ioe) {
-            diagnostics.putString("\n Unable to attach to target VM: " +
-                                  ioe.getMessage());
-        } catch (IllegalConnectorArgumentsException icae) {
-            diagnostics.putString("\n Invalid connector arguments: " +
-                                  icae.getMessage());
-        }
-        return null;
-    }
-
-    private Session internalListen(ListeningConnector connector,
-                                   Map arguments) {
-        try {
-            VirtualMachine vm = connector.accept(arguments);
-            return new Session(vm, this, diagnostics);
-        } catch (IOException ioe) {
-            diagnostics.putString(
-                  "\n Unable to accept connection to target VM: " +
-                                  ioe.getMessage());
-        } catch (IllegalConnectorArgumentsException icae) {
-            diagnostics.putString("\n Invalid connector arguments: " +
-                                  icae.getMessage());
-        }
-        return null;
-    }
-
-    /*
-     * Connect via user specified arguments
-     * @return true on success
-     */
-    public boolean explictStart(Connector connector, Map arguments)
-                                           throws VMLaunchFailureException {
-        Session newSession = null;
-
-        endSession();
-
-        if (connector instanceof LaunchingConnector) {
-            // we were launched, use ChildSession
-            newSession = new ChildSession(this, (LaunchingConnector)connector,
-                                          arguments,
-                                          appInput, appOutput, appError,
-                                          diagnostics);
-        } else if (connector instanceof AttachingConnector) {
-            newSession = internalAttach((AttachingConnector)connector,
-                                        arguments);
-        } else if (connector instanceof ListeningConnector) {
-            newSession = internalListen((ListeningConnector)connector,
-                                        arguments);
-        } else {
-            diagnostics.putString("\n Unknown connector: " + connector);
-        }
-        if (newSession != null) {
-            startSession(newSession);
-        }
-        return newSession != null;
-    }
-
-    /*
-     * Detach from VM.  If VM was started by debugger, terminate it.
-     */
-    public void detach() throws NoSessionException {
-        ensureActiveSession();
-        endSession();
-    }
-
-    private void startSession(Session s) throws VMLaunchFailureException {
-        if (!s.attach()) {
-            throw new VMLaunchFailureException();
-        }
-        session = s;
-        EventRequestManager em = vm().eventRequestManager();
-        ClassPrepareRequest classPrepareRequest = em.createClassPrepareRequest();
-        //### We must allow the deferred breakpoints to be resolved before
-        //### we continue executing the class.  We could optimize if there
-        //### were no deferred breakpoints outstanding for a particular class.
-        //### Can we do this with JDI?
-        classPrepareRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
-        classPrepareRequest.enable();
-        ClassUnloadRequest classUnloadRequest = em.createClassUnloadRequest();
-        classUnloadRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
-        classUnloadRequest.enable();
-        ThreadStartRequest threadStartRequest = em.createThreadStartRequest();
-        threadStartRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
-        threadStartRequest.enable();
-        ThreadDeathRequest threadDeathRequest = em.createThreadDeathRequest();
-        threadDeathRequest.setSuspendPolicy(EventRequest.SUSPEND_NONE);
-        threadDeathRequest.enable();
-        ExceptionRequest exceptionRequest =
-                                em.createExceptionRequest(null, false, true);
-        exceptionRequest.setSuspendPolicy(EventRequest.SUSPEND_ALL);
-        exceptionRequest.enable();
-        validateThreadInfo();
-        session.interrupted = true;
-        notifySessionStart();
-    }
-
-    void endSession() {
-        if (session != null) {
-            session.detach();
-            session = null;
-            invalidateThreadInfo();
-            notifySessionDeath();
-        }
-    }
-
-    /*
-     * Suspend all VM activity.
-     */
-
-    public void interrupt() throws NoSessionException {
-        ensureActiveSession();
-        vm().suspend();
-        //### Is it guaranteed that the interrupt has happened?
-        validateThreadInfo();
-        session.interrupted = true;
-        notifyInterrupted();
-    }
-
-    /*
-     * Resume interrupted VM.
-     */
-
-    public void go() throws NoSessionException, VMNotInterruptedException {
-        ensureActiveSession();
-        invalidateThreadInfo();
-        session.interrupted = false;
-        notifyContinued();
-        vm().resume();
-    }
-
-    /*
-     * Stepping.
-     */
-    void clearPreviousStep(ThreadReference thread) {
-        /*
-         * A previous step may not have completed on this thread;
-         * if so, it gets removed here.
-         */
-         EventRequestManager mgr = vm().eventRequestManager();
-         for (StepRequest request : mgr.stepRequests()) {
-             if (request.thread().equals(thread)) {
-                 mgr.deleteEventRequest(request);
-                 break;
-             }
-         }
-    }
-
-    private void generalStep(ThreadReference thread, int size, int depth)
-                        throws NoSessionException {
-        ensureActiveSession();
-        invalidateThreadInfo();
-        session.interrupted = false;
-        notifyContinued();
-
-        clearPreviousStep(thread);
-        EventRequestManager reqMgr = vm().eventRequestManager();
-        StepRequest request = reqMgr.createStepRequest(thread,
-                                                       size, depth);
-        // We want just the next step event and no others
-        request.addCountFilter(1);
-        request.enable();
-        vm().resume();
-    }
-
-    public void stepIntoInstruction(ThreadReference thread)
-                        throws NoSessionException {
-        generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_INTO);
-    }
-
-    public void stepOverInstruction(ThreadReference thread)
-                        throws NoSessionException {
-        generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OVER);
-    }
-
-    public void stepIntoLine(ThreadReference thread)
-                        throws NoSessionException,
-                        AbsentInformationException {
-        generalStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_INTO);
-    }
-
-    public void stepOverLine(ThreadReference thread)
-                        throws NoSessionException,
-                        AbsentInformationException {
-        generalStep(thread, StepRequest.STEP_LINE, StepRequest.STEP_OVER);
-    }
-
-    public void stepOut(ThreadReference thread)
-                        throws NoSessionException {
-        generalStep(thread, StepRequest.STEP_MIN, StepRequest.STEP_OUT);
-    }
-
-    /*
-     * Thread control.
-     */
-
-    public void suspendThread(ThreadReference thread) throws NoSessionException {
-        ensureActiveSession();
-        thread.suspend();
-    }
-
-    public void resumeThread(ThreadReference thread) throws NoSessionException {
-        ensureActiveSession();
-        thread.resume();
-    }
-
-    public void stopThread(ThreadReference thread) throws NoSessionException {
-        ensureActiveSession();
-        //### Need an exception now.  Which one to use?
-        //thread.stop();
-    }
-
-    /*
-     * ThreadInfo objects -- Allow query of thread status and stack.
-     */
-
-    private List threadInfoList = new LinkedList();
-    //### Should be weak! (in the value, not the key)
-    private HashMap threadInfoMap = new HashMap();
-
-    public ThreadInfo threadInfo(ThreadReference thread) {
-        if (session == null || thread == null) {
-            return null;
-        }
-        ThreadInfo info = threadInfoMap.get(thread);
-        if (info == null) {
-            //### Should not hardcode initial frame count and prefetch here!
-            //info = new ThreadInfo(thread, 10, 10);
-            info = new ThreadInfo(thread);
-            if (session.interrupted) {
-                info.validate();
-            }
-            threadInfoList.add(info);
-            threadInfoMap.put(thread, info);
-        }
-        return info;
-    }
-
-     void validateThreadInfo() {
-        session.interrupted = true;
-        for (ThreadInfo threadInfo : threadInfoList) {
-            threadInfo.validate();
-            }
-    }
-
-    private void invalidateThreadInfo() {
-        if (session != null) {
-            session.interrupted = false;
-            for (ThreadInfo threadInfo : threadInfoList) {
-                threadInfo.invalidate();
-            }
-        }
-    }
-
-    void removeThreadInfo(ThreadReference thread) {
-        ThreadInfo info = threadInfoMap.get(thread);
-        if (info != null) {
-            info.invalidate();
-            threadInfoMap.remove(thread);
-            threadInfoList.remove(info);
-        }
-    }
-
-    /*
-     * Listen for Session control events.
-     */
-
-    private void notifyInterrupted() {
-      ArrayList l = new ArrayList(sessionListeners);
-        EventObject evt = new EventObject(this);
-        for (int i = 0; i < l.size(); i++) {
-            l.get(i).sessionInterrupt(evt);
-        }
-    }
-
-    private void notifyContinued() {
-        ArrayList l = new ArrayList(sessionListeners);
-        EventObject evt = new EventObject(this);
-        for (int i = 0; i < l.size(); i++) {
-            l.get(i).sessionContinue(evt);
-        }
-    }
-
-    private void notifySessionStart() {
-        ArrayList l = new ArrayList(sessionListeners);
-        EventObject evt = new EventObject(this);
-        for (int i = 0; i < l.size(); i++) {
-            l.get(i).sessionStart(evt);
-        }
-    }
-
-    private void notifySessionDeath() {
-/*** noop for now
-        ArrayList l = new ArrayList(sessionListeners);
-        EventObject evt = new EventObject(this);
-        for (int i = 0; i < l.size(); i++) {
-            ((SessionListener)l.get(i)).sessionDeath(evt);
-        }
-****/
-    }
-
-    /*
-     * Listen for input and output requests from the application
-     * being debugged.  These are generated only when the debuggee
-     * is spawned as a child of the debugger.
-     */
-
-    private Object inputLock = new Object();
-    private LinkedList inputBuffer = new LinkedList();
-
-    private void resetInputBuffer() {
-        synchronized (inputLock) {
-            inputBuffer = new LinkedList();
-        }
-    }
-
-    public void sendLineToApplication(String line) {
-        synchronized (inputLock) {
-            inputBuffer.addFirst(line);
-            inputLock.notifyAll();
-        }
-    }
-
-    private InputListener appInput = new InputListener() {
-        @Override
-        public String getLine() {
-            // Don't allow reader to be interrupted -- catch and retry.
-            String line = null;
-            while (line == null) {
-                synchronized (inputLock) {
-                    try {
-                        while (inputBuffer.size() < 1) {
-                            inputLock.wait();
-                        }
-                        line = inputBuffer.removeLast();
-                    } catch (InterruptedException e) {}
-                }
-            }
-            // We must not be holding inputLock here, as the listener
-            // that we call to echo a line might call us re-entrantly
-            // to provide another line of input.
-            // Run in Swing event dispatcher thread.
-            final String input = line;
-            SwingUtilities.invokeLater(new Runnable() {
-                @Override
-                public void run() {
-                    echoInputLine(input);
-                }
-            });
-            return line;
-        }
-    };
-
-    private static String newline = System.getProperty("line.separator");
-
-    private void echoInputLine(String line) {
-        ArrayList l = new ArrayList(appEchoListeners);
-        for (int i = 0; i < l.size(); i++) {
-            OutputListener ol = l.get(i);
-            ol.putString(line);
-            ol.putString(newline);
-        }
-    }
-
-    private OutputListener appOutput = new OutputListener() {
-      @Override
-        public void putString(String string) {
-            ArrayList l = new ArrayList(appEchoListeners);
-            for (int i = 0; i < l.size(); i++) {
-                l.get(i).putString(string);
-            }
-        }
-    };
-
-    private OutputListener appError = new OutputListener() {
-      @Override
-        public void putString(String string) {
-            ArrayList l = new ArrayList(appEchoListeners);
-            for (int i = 0; i < l.size(); i++) {
-                l.get(i).putString(string);
-            }
-        }
-    };
-
-   private OutputListener diagnostics = new OutputListener() {
-      @Override
-        public void putString(String string) {
-            ArrayList l = new ArrayList(diagnosticsListeners);
-            for (int i = 0; i < l.size(); i++) {
-                l.get(i).putString(string);
-            }
-        }
-   };
-
-  /////////////    Spec Request Creation/Deletion/Query   ///////////
-
-    private EventRequestSpecList specList = new EventRequestSpecList(this);
-
-    public BreakpointSpec
-    createSourceLineBreakpoint(String sourceName, int line) {
-        return specList.createSourceLineBreakpoint(sourceName, line);
-    }
-
-    public BreakpointSpec
-    createClassLineBreakpoint(String classPattern, int line) {
-        return specList.createClassLineBreakpoint(classPattern, line);
-    }
-
-    public BreakpointSpec
-    createMethodBreakpoint(String classPattern,
-                           String methodId, List methodArgs) {
-        return specList.createMethodBreakpoint(classPattern,
-                                                 methodId, methodArgs);
-    }
-
-    public ExceptionSpec
-    createExceptionIntercept(String classPattern,
-                             boolean notifyCaught,
-                             boolean notifyUncaught) {
-        return specList.createExceptionIntercept(classPattern,
-                                                   notifyCaught,
-                                                   notifyUncaught);
-    }
-
-    public AccessWatchpointSpec
-    createAccessWatchpoint(String classPattern, String fieldId) {
-        return specList.createAccessWatchpoint(classPattern, fieldId);
-    }
-
-    public ModificationWatchpointSpec
-    createModificationWatchpoint(String classPattern, String fieldId) {
-        return specList.createModificationWatchpoint(classPattern,
-                                                       fieldId);
-    }
-
-    public void delete(EventRequestSpec spec) {
-        specList.delete(spec);
-    }
-
-    void resolve(ReferenceType refType) {
-        specList.resolve(refType);
-    }
-
-    public void install(EventRequestSpec spec) {
-        specList.install(spec, vm());
-    }
-
-    public List eventRequestSpecs() {
-        return specList.eventRequestSpecs();
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/FrameIndexOutOfBoundsException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/FrameIndexOutOfBoundsException.java
deleted file mode 100644
index 57d4e2a6d9c..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/FrameIndexOutOfBoundsException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-public class FrameIndexOutOfBoundsException extends IndexOutOfBoundsException {
-
-    private static final long serialVersionUID = -4870148107027371437L;
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/JDIEventSource.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/JDIEventSource.java
deleted file mode 100644
index 2d92094d0d5..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/JDIEventSource.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.*;
-import com.sun.jdi.event.*;
-
-import com.sun.tools.example.debug.event.*;
-
-import javax.swing.SwingUtilities;
-
-/**
- */
-class JDIEventSource extends Thread {
-
-    private /*final*/ EventQueue queue;
-    private /*final*/ Session session;
-    private /*final*/ ExecutionManager runtime;
-    private final JDIListener firstListener = new FirstListener();
-
-    private boolean wantInterrupt;  //### Hack
-
-    /**
-     * Create event source.
-     */
-    JDIEventSource(Session session) {
-        super("JDI Event Set Dispatcher");
-        this.session = session;
-        this.runtime = session.runtime;
-        this.queue = session.vm.eventQueue();
-    }
-
-    @Override
-    public void run() {
-        try {
-            runLoop();
-        } catch (Exception exc) {
-            //### Do something different for InterruptedException???
-            // just exit
-        }
-        session.running = false;
-    }
-
-    private void runLoop() throws InterruptedException {
-        AbstractEventSet es;
-        do {
-            EventSet jdiEventSet = queue.remove();
-            es = AbstractEventSet.toSpecificEventSet(jdiEventSet);
-            session.interrupted = es.suspendedAll();
-            dispatchEventSet(es);
-        } while(!(es instanceof VMDisconnectEventSet));
-    }
-
-    //### Gross foul hackery!
-    private void dispatchEventSet(final AbstractEventSet es) {
-        SwingUtilities.invokeLater(new Runnable() {
-            @Override
-            public void run() {
-                boolean interrupted = es.suspendedAll();
-                es.notify(firstListener);
-                boolean wantInterrupt = JDIEventSource.this.wantInterrupt;
-                for (JDIListener jl : session.runtime.jdiListeners) {
-                    es.notify(jl);
-                }
-                if (interrupted && !wantInterrupt) {
-                    session.interrupted = false;
-                    //### Catch here is a hack
-                    try {
-                        session.vm.resume();
-                    } catch (VMDisconnectedException ee) {}
-                }
-                if (es instanceof ThreadDeathEventSet) {
-                    ThreadReference t = ((ThreadDeathEventSet)es).getThread();
-                    session.runtime.removeThreadInfo(t);
-                }
-            }
-        });
-    }
-
-    private void finalizeEventSet(AbstractEventSet es) {
-        if (session.interrupted && !wantInterrupt) {
-            session.interrupted = false;
-            //### Catch here is a hack
-            try {
-                session.vm.resume();
-            } catch (VMDisconnectedException ee) {}
-        }
-        if (es instanceof ThreadDeathEventSet) {
-            ThreadReference t = ((ThreadDeathEventSet)es).getThread();
-            session.runtime.removeThreadInfo(t);
-        }
-    }
-
-    //### This is a Hack, deal with it
-    private class FirstListener implements JDIListener {
-
-        @Override
-        public void accessWatchpoint(AccessWatchpointEventSet e) {
-            session.runtime.validateThreadInfo();
-            wantInterrupt = true;
-        }
-
-        @Override
-        public void classPrepare(ClassPrepareEventSet e)  {
-            wantInterrupt = false;
-            runtime.resolve(e.getReferenceType());
-        }
-
-        @Override
-        public void classUnload(ClassUnloadEventSet e)  {
-            wantInterrupt = false;
-        }
-
-        @Override
-        public void exception(ExceptionEventSet e)  {
-            wantInterrupt = true;
-        }
-
-        @Override
-        public void locationTrigger(LocationTriggerEventSet e)  {
-            session.runtime.validateThreadInfo();
-            wantInterrupt = true;
-        }
-
-        @Override
-        public void modificationWatchpoint(ModificationWatchpointEventSet e)  {
-            session.runtime.validateThreadInfo();
-            wantInterrupt = true;
-        }
-
-        @Override
-        public void threadDeath(ThreadDeathEventSet e)  {
-            wantInterrupt = false;
-        }
-
-        @Override
-        public void threadStart(ThreadStartEventSet e)  {
-            wantInterrupt = false;
-        }
-
-        @Override
-        public void vmDeath(VMDeathEventSet e)  {
-            //### Should have some way to notify user
-            //### that VM died before the session ended.
-            wantInterrupt = false;
-        }
-
-        @Override
-        public void vmDisconnect(VMDisconnectEventSet e)  {
-            //### Notify user?
-            wantInterrupt = false;
-            session.runtime.endSession();
-        }
-
-        @Override
-        public void vmStart(VMStartEventSet e)  {
-            //### Do we need to do anything with it?
-            wantInterrupt = false;
-        }
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java
deleted file mode 100644
index f7d66ce2d52..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/LineBreakpointSpec.java
+++ /dev/null
@@ -1,130 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.*;
-import java.util.List;
-
-public class LineBreakpointSpec extends BreakpointSpec {
-    int lineNumber;
-
-    LineBreakpointSpec(EventRequestSpecList specs,
-                       ReferenceTypeSpec refSpec, int lineNumber) {
-        super(specs, refSpec);
-        this.lineNumber = lineNumber;
-    }
-
-    /**
-     * The 'refType' is known to match.
-     */
-    @Override
-    void resolve(ReferenceType refType) throws InvalidTypeException,
-                                             LineNotFoundException {
-        if (!(refType instanceof ClassType)) {
-            throw new InvalidTypeException();
-        }
-        Location location = location((ClassType)refType);
-        setRequest(refType.virtualMachine().eventRequestManager()
-                   .createBreakpointRequest(location));
-    }
-
-    private Location location(ClassType clazz) throws
-                                            LineNotFoundException {
-        Location location = null;
-        try {
-            List locs = clazz.locationsOfLine(lineNumber());
-            if (locs.size() == 0) {
-                throw new LineNotFoundException();
-            }
-            // TODO handle multiple locations
-            location = locs.get(0);
-            if (location.method() == null) {
-                throw new LineNotFoundException();
-            }
-        } catch (AbsentInformationException e) {
-            /*
-             * TO DO: throw something more specific, or allow
-             * AbsentInfo exception to pass through.
-             */
-            throw new LineNotFoundException();
-        }
-        return location;
-    }
-
-    public int lineNumber() {
-        return lineNumber;
-    }
-
-    @Override
-    public int hashCode() {
-        return refSpec.hashCode() + lineNumber;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof LineBreakpointSpec) {
-            LineBreakpointSpec breakpoint = (LineBreakpointSpec)obj;
-
-            return refSpec.equals(breakpoint.refSpec) &&
-                   (lineNumber == breakpoint.lineNumber);
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public String errorMessageFor(Exception e) {
-        if (e instanceof LineNotFoundException) {
-            return ("No code at line " + lineNumber() + " in " + refSpec);
-        } else if (e instanceof InvalidTypeException) {
-            return ("Breakpoints can be located only in classes. " +
-                        refSpec + " is an interface or array");
-        } else {
-            return super.errorMessageFor( e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("breakpoint ");
-        sb.append(refSpec.toString());
-        sb.append(':');
-        sb.append(lineNumber);
-        sb.append(" (");
-        sb.append(getStatusString());
-        sb.append(')');
-        return sb.toString();
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MalformedMemberNameException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MalformedMemberNameException.java
deleted file mode 100644
index 1980893a361..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MalformedMemberNameException.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-class MalformedMemberNameException extends Exception {
-
-    private static final long serialVersionUID = -7726664097374844485L;
-
-    public MalformedMemberNameException() {
-        super();
-    }
-
-    public MalformedMemberNameException(String s) {
-        super(s);
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java
deleted file mode 100644
index b414443faf7..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodBreakpointSpec.java
+++ /dev/null
@@ -1,346 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.*;
-import java.util.ArrayList;
-import java.util.List;
-
-public class MethodBreakpointSpec extends BreakpointSpec {
-    String methodId;
-    List methodArgs;
-
-    MethodBreakpointSpec(EventRequestSpecList specs,
-                         ReferenceTypeSpec refSpec,
-                         String methodId, List methodArgs) {
-        super(specs, refSpec);
-        this.methodId = methodId;
-        this.methodArgs = methodArgs;
-    }
-
-    /**
-     * The 'refType' is known to match.
-     */
-    @Override
-    void resolve(ReferenceType refType) throws MalformedMemberNameException,
-                                             AmbiguousMethodException,
-                                             InvalidTypeException,
-                                             NoSuchMethodException,
-                                             NoSessionException {
-        if (!isValidMethodName(methodId)) {
-            throw new MalformedMemberNameException(methodId);
-        }
-        if (!(refType instanceof ClassType)) {
-            throw new InvalidTypeException();
-        }
-        Location location = location((ClassType)refType);
-        setRequest(refType.virtualMachine().eventRequestManager()
-                   .createBreakpointRequest(location));
-    }
-
-    private Location location(ClassType clazz) throws
-                                               AmbiguousMethodException,
-                                               NoSuchMethodException,
-                                               NoSessionException {
-        Method method = findMatchingMethod(clazz);
-        Location location = method.location();
-        return location;
-    }
-
-    public String methodName() {
-        return methodId;
-    }
-
-    public List methodArgs() {
-        return methodArgs;
-    }
-
-    @Override
-    public int hashCode() {
-        return refSpec.hashCode() +
-            ((methodId != null) ? methodId.hashCode() : 0) +
-            ((methodArgs != null) ? methodArgs.hashCode() : 0);
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof MethodBreakpointSpec) {
-            MethodBreakpointSpec breakpoint = (MethodBreakpointSpec)obj;
-
-            return methodId.equals(breakpoint.methodId) &&
-                   methodArgs.equals(breakpoint.methodArgs) &&
-                   refSpec.equals(breakpoint.refSpec);
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public String errorMessageFor(Exception e) {
-        if (e instanceof AmbiguousMethodException) {
-            return ("Method " + methodName() + " is overloaded; specify arguments");
-            /*
-             * TO DO: list the methods here
-             */
-        } else if (e instanceof NoSuchMethodException) {
-            return ("No method " + methodName() + " in " + refSpec);
-        } else if (e instanceof InvalidTypeException) {
-            return ("Breakpoints can be located only in classes. " +
-                        refSpec + " is an interface or array");
-        } else {
-            return super.errorMessageFor( e);
-        }
-    }
-
-    @Override
-    public String toString() {
-        StringBuilder sb = new StringBuilder("breakpoint ");
-        sb.append(refSpec.toString());
-        sb.append('.');
-        sb.append(methodId);
-        if (methodArgs != null) {
-            boolean first = true;
-            sb.append('(');
-            for (String name : methodArgs) {
-                if (!first) {
-                    sb.append(',');
-                }
-                sb.append(name);
-                first = false;
-            }
-            sb.append(")");
-        }
-        sb.append(" (");
-        sb.append(getStatusString());
-        sb.append(')');
-        return sb.toString();
-    }
-
-    private boolean isValidMethodName(String s) {
-        return isJavaIdentifier(s) ||
-               s.equals("") ||
-               s.equals("");
-    }
-
-    /*
-     * Compare a method's argument types with a Vector of type names.
-     * Return true if each argument type has a name identical to the
-     * corresponding string in the vector (allowing for varargs)
-     * and if the number of arguments in the method matches the
-     * number of names passed
-     */
-    private boolean compareArgTypes(Method method, List nameList) {
-        List argTypeNames = method.argumentTypeNames();
-
-        // If argument counts differ, we can stop here
-        if (argTypeNames.size() != nameList.size()) {
-            return false;
-        }
-
-        // Compare each argument type's name
-        int nTypes = argTypeNames.size();
-        for (int i = 0; i < nTypes; ++i) {
-            String comp1 = argTypeNames.get(i);
-            String comp2 = nameList.get(i);
-            if (! comp1.equals(comp2)) {
-                /*
-                 * We have to handle varargs.  EG, the
-                 * method's last arg type is xxx[]
-                 * while the nameList contains xxx...
-                 * Note that the nameList can also contain
-                 * xxx[] in which case we don't get here.
-                 */
-                if (i != nTypes - 1 ||
-                    !method.isVarArgs()  ||
-                    !comp2.endsWith("...")) {
-                    return false;
-                }
-                /*
-                 * The last types differ, it is a varargs
-                 * method and the nameList item is varargs.
-                 * We just have to compare the type names, eg,
-                 * make sure we don't have xxx[] for the method
-                 * arg type and yyy... for the nameList item.
-                 */
-                int comp1Length = comp1.length();
-                if (comp1Length + 1 != comp2.length()) {
-                    // The type names are different lengths
-                    return false;
-                }
-                // We know the two type names are the same length
-                if (!comp1.regionMatches(0, comp2, 0, comp1Length - 2)) {
-                    return false;
-                }
-                // We do have xxx[] and xxx... as the last param type
-                return true;
-            }
-        }
-
-        return true;
-    }
-
-  private VirtualMachine vm() {
-    return request.virtualMachine();
-  }
-
-  /**
-     * Remove unneeded spaces and expand class names to fully
-     * qualified names, if necessary and possible.
-     */
-    private String normalizeArgTypeName(String name) throws NoSessionException {
-        /*
-         * Separate the type name from any array modifiers,
-         * stripping whitespace after the name ends.
-         */
-        int i = 0;
-        StringBuilder typePart = new StringBuilder();
-        StringBuilder arrayPart = new StringBuilder();
-        name = name.trim();
-        int nameLength = name.length();
-        /*
-         * For varargs, there can be spaces before the ... but not
-         * within the ...  So, we will just ignore the ...
-         * while stripping blanks.
-         */
-        boolean isVarArgs = name.endsWith("...");
-        if (isVarArgs) {
-            nameLength -= 3;
-        }
-
-        while (i < nameLength) {
-            char c = name.charAt(i);
-            if (Character.isWhitespace(c) || c == '[') {
-                break;      // name is complete
-            }
-            typePart.append(c);
-            i++;
-        }
-        while (i < nameLength) {
-            char c = name.charAt(i);
-            if ( (c == '[') || (c == ']')) {
-                arrayPart.append(c);
-            } else if (!Character.isWhitespace(c)) {
-                throw new IllegalArgumentException(
-                                                "Invalid argument type name");
-
-            }
-            i++;
-        }
-
-        name = typePart.toString();
-
-        /*
-         * When there's no sign of a package name already,
-         * try to expand the
-         * the name to a fully qualified class name
-         */
-        if ((name.indexOf('.') == -1) || name.startsWith("*.")) {
-            try {
-                List refs = specs.runtime.findClassesMatchingPattern(name);
-                if (refs.size() > 0) {  //### ambiguity???
-                    name = ((ReferenceType)(refs.get(0))).name();
-                }
-            } catch (IllegalArgumentException e) {
-                // We'll try the name as is
-            }
-        }
-        name += arrayPart.toString();
-        if (isVarArgs) {
-            name += "...";
-        }
-        return name;
-    }
-
-    /*
-     * Attempt an unambiguous match of the method name and
-     * argument specification to a method. If no arguments
-     * are specified, the method must not be overloaded.
-     * Otherwise, the argument types much match exactly
-     */
-    private Method findMatchingMethod(ClassType clazz)
-                                        throws AmbiguousMethodException,
-                                               NoSuchMethodException,
-                                               NoSessionException  {
-
-        // Normalize the argument string once before looping below.
-        List argTypeNames = null;
-        if (methodArgs() != null) {
-            argTypeNames = new ArrayList(methodArgs().size());
-            for (String name : methodArgs()) {
-                name = normalizeArgTypeName(name);
-                argTypeNames.add(name);
-            }
-        }
-
-        // Check each method in the class for matches
-        Method firstMatch = null;  // first method with matching name
-        Method exactMatch = null;  // (only) method with same name & sig
-        int matchCount = 0;        // > 1 implies overload
-        for (Method candidate : clazz.methods()) {
-            if (candidate.name().equals(methodName())) {
-                matchCount++;
-
-                // Remember the first match in case it is the only one
-                if (matchCount == 1) {
-                    firstMatch = candidate;
-                }
-
-                // If argument types were specified, check against candidate
-                if ((argTypeNames != null)
-                        && compareArgTypes(candidate, argTypeNames) == true) {
-                    exactMatch = candidate;
-                    break;
-                }
-            }
-        }
-
-        // Determine method for breakpoint
-        Method method = null;
-        if (exactMatch != null) {
-            // Name and signature match
-            method = exactMatch;
-        } else if ((argTypeNames == null) && (matchCount > 0)) {
-            // At least one name matched and no arg types were specified
-            if (matchCount == 1) {
-                method = firstMatch;       // Only one match; safe to use it
-            } else {
-                throw new AmbiguousMethodException();
-            }
-        } else {
-            throw new NoSuchMethodException(methodName());
-        }
-        return method;
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodNotFoundException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodNotFoundException.java
deleted file mode 100644
index 820c35cc61b..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/MethodNotFoundException.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-public class MethodNotFoundException extends Exception
-{
-    private static final long serialVersionUID = -2064968107599632609L;
-
-    public MethodNotFoundException()
-    {
-        super();
-    }
-
-    public MethodNotFoundException(String s)
-    {
-        super(s);
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ModificationWatchpointSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ModificationWatchpointSpec.java
deleted file mode 100644
index b8f2b86e65a..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ModificationWatchpointSpec.java
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.*;
-
-public class ModificationWatchpointSpec extends WatchpointSpec {
-
-    ModificationWatchpointSpec(EventRequestSpecList specs,
-                         ReferenceTypeSpec refSpec, String fieldId) {
-        super(specs, refSpec,  fieldId);
-    }
-
-    /**
-     * The 'refType' is known to match.
-     */
-    @Override
-    void resolve(ReferenceType refType) throws InvalidTypeException,
-                                             NoSuchFieldException {
-        if (!(refType instanceof ClassType)) {
-            throw new InvalidTypeException();
-        }
-        Field field = refType.fieldByName(fieldId);
-        if (field == null) {
-            throw new NoSuchFieldException(fieldId);
-        }
-        setRequest(refType.virtualMachine().eventRequestManager()
-                   .createModificationWatchpointRequest(field));
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        return (obj instanceof ModificationWatchpointSpec) &&
-            super.equals(obj);
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoSessionException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoSessionException.java
deleted file mode 100644
index 3e92e2eb167..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoSessionException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-public class NoSessionException extends Exception {
-
-    private static final long serialVersionUID = -7324357828115128603L;
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoThreadException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoThreadException.java
deleted file mode 100644
index 12512094f4d..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/NoThreadException.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-public class NoThreadException extends Exception {
-
-    private static final long serialVersionUID = 1846613539928921998L;
-
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/OutputListener.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/OutputListener.java
deleted file mode 100644
index 8bb6701595e..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/OutputListener.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-public interface OutputListener {
-    void putString(String str);
-    //void putLine(String line);
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/PatternReferenceTypeSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/PatternReferenceTypeSpec.java
deleted file mode 100644
index fa034aea3b4..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/PatternReferenceTypeSpec.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.*;
-import java.util.StringTokenizer;
-
-class PatternReferenceTypeSpec implements ReferenceTypeSpec {
-    final boolean isWild;
-    final String classId;
-
-    PatternReferenceTypeSpec(String classId)
-//                             throws ClassNotFoundException
-    {
-//        checkClassName(classId);
-        isWild = classId.startsWith("*.");
-        if (isWild) {
-            this.classId = classId.substring(1);
-        } else {
-            this.classId = classId;
-        }
-    }
-
-    /**
-     * Does the specified ReferenceType match this spec.
-     */
-    @Override
-    public boolean matches(ReferenceType refType) {
-        if (isWild) {
-            return refType.name().endsWith(classId);
-        } else {
-            return refType.name().equals(classId);
-        }
-    }
-
-    @Override
-    public int hashCode() {
-        return classId.hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof PatternReferenceTypeSpec) {
-            PatternReferenceTypeSpec spec = (PatternReferenceTypeSpec)obj;
-
-            return classId.equals(spec.classId) && (isWild == spec.isWild);
-        } else {
-            return false;
-        }
-    }
-
-    private void checkClassName(String className) throws ClassNotFoundException {
-        // Do stricter checking of class name validity on deferred
-        //  because if the name is invalid, it will
-        // never match a future loaded class, and we'll be silent
-        // about it.
-        StringTokenizer tokenizer = new StringTokenizer(className, ".");
-        boolean first = true;
-        while (tokenizer.hasMoreTokens()) {
-            String token = tokenizer.nextToken();
-            // Each dot-separated piece must be a valid identifier
-            // and the first token can also be "*". (Note that
-            // numeric class ids are not permitted. They must
-            // match a loaded class.)
-            if (!Utils.isJavaIdentifier(token) && !(first && token.equals("*"))) {
-                throw new ClassNotFoundException();
-            }
-            first = false;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return isWild? "*" + classId : classId;
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Session.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Session.java
deleted file mode 100644
index 883834a07a1..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Session.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.VirtualMachine;
-import com.sun.jdi.VMDisconnectedException;
-
-/**
- * Our repository of what we know about the state of one
- * running VM.
- */
-class Session {
-
-    final VirtualMachine vm;
-    final ExecutionManager runtime;
-    final OutputListener diagnostics;
-
-    boolean running = true;  // Set false by JDIEventSource
-    boolean interrupted = false;  // Set false by JDIEventSource
-
-    private JDIEventSource eventSourceThread = null;
-    private int traceFlags;
-    private boolean dead = false;
-
-    public Session(VirtualMachine vm, ExecutionManager runtime,
-                   OutputListener diagnostics) {
-        this.vm = vm;
-        this.runtime = runtime;
-        this.diagnostics = diagnostics;
-        this.traceFlags = VirtualMachine.TRACE_NONE;
-    }
-
-    /**
-     * Determine if VM is interrupted, i.e, present and not running.
-     */
-    public boolean isInterrupted() {
-        return interrupted;
-    }
-
-    public void setTraceMode(int traceFlags) {
-        this.traceFlags = traceFlags;
-        if (!dead) {
-            vm.setDebugTraceMode(traceFlags);
-        }
-    }
-
-    public boolean attach() {
-        vm.setDebugTraceMode(traceFlags);
-        diagnostics.putString("Connected to VM");
-        eventSourceThread = new JDIEventSource(this);
-        eventSourceThread.start();
-        return true;
-    }
-
-    public void detach() {
-        if (!dead) {
-            eventSourceThread.interrupt();
-            eventSourceThread = null;
-            //### The VM may already be disconnected
-            //### if the debuggee did a System.exit().
-            //### Exception handler here is a kludge,
-            //### Rather, there are many other places
-            //### where we need to handle this exception,
-            //### and initiate a detach due to an error
-            //### condition, e.g., connection failure.
-            try {
-                vm.dispose();
-            } catch (VMDisconnectedException ee) {}
-            dead = true;
-            diagnostics.putString("Disconnected from VM");
-        }
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SessionListener.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SessionListener.java
deleted file mode 100644
index e13c4d70e72..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SessionListener.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import java.util.EventObject;
-import java.util.EventListener;
-
-public interface SessionListener extends EventListener {
-
-    void sessionStart(EventObject e);
-
-    void sessionInterrupt(EventObject e);
-    void sessionContinue(EventObject e);
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SourceNameReferenceTypeSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SourceNameReferenceTypeSpec.java
deleted file mode 100644
index 36061bfc487..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SourceNameReferenceTypeSpec.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.*;
-
-class SourceNameReferenceTypeSpec implements ReferenceTypeSpec {
-    final String sourceName;
-    final int linenumber;
-
-    SourceNameReferenceTypeSpec(String sourceName, int linenumber) {
-        this.sourceName = sourceName;
-        this.linenumber = linenumber;
-    }
-
-    /**
-     * Does the specified ReferenceType match this spec.
-     */
-    @Override
-    public boolean matches(ReferenceType refType) {
-        try {
-            if (refType.sourceName().equals(sourceName)) {
-                try {
-                    refType.locationsOfLine(linenumber);
-                    // if we don't throw an exception then it was found
-                    return true;
-                } catch(AbsentInformationException exc) {
-                } catch(ObjectCollectedException  exc) {
-                }
-            }
-        } catch(AbsentInformationException exc) {
-            // for sourceName(), fall through
-        }
-        return false;
-    }
-
-    @Override
-    public int hashCode() {
-        return sourceName.hashCode() + linenumber;
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof SourceNameReferenceTypeSpec) {
-            SourceNameReferenceTypeSpec spec = (SourceNameReferenceTypeSpec)obj;
-
-            return sourceName.equals(spec.sourceName) &&
-                              (linenumber == spec.linenumber);
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public String toString() {
-        return sourceName + "@" + linenumber;
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecErrorEvent.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecErrorEvent.java
deleted file mode 100644
index baab1291d2d..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecErrorEvent.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-public class SpecErrorEvent extends SpecEvent {
-
-    private static final long serialVersionUID = 8162634387866409578L;
-    private Exception reason;
-
-    public SpecErrorEvent(EventRequestSpec eventRequestSpec,
-                                 Exception reason) {
-        super(eventRequestSpec);
-        this.reason = reason;
-    }
-
-    public Exception getReason() {
-        return reason;
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecEvent.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecEvent.java
deleted file mode 100644
index 7a321ef4aaa..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecEvent.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import java.util.EventObject;
-
-import com.sun.jdi.request.EventRequest;
-
-public class SpecEvent extends EventObject {
-
-    private static final long serialVersionUID = 4820735456787276230L;
-    private EventRequestSpec eventRequestSpec;
-
-    public SpecEvent(EventRequestSpec eventRequestSpec) {
-        super(eventRequestSpec.specs);
-        this.eventRequestSpec = eventRequestSpec;
-    }
-
-    public EventRequestSpec getEventRequestSpec() {
-        return eventRequestSpec;
-    }
-
-    public EventRequest getEventRequest() {
-        return eventRequestSpec.getEventRequest();
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecListener.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecListener.java
deleted file mode 100644
index 2e5df596ea4..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/SpecListener.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import java.util.EventListener;
-
-public interface SpecListener extends EventListener {
-
-    void breakpointSet(SpecEvent e);
-    void breakpointDeferred(SpecEvent e);
-    void breakpointDeleted(SpecEvent e);
-    void breakpointResolved(SpecEvent e);
-    void breakpointError(SpecErrorEvent e);
-
-    void watchpointSet(SpecEvent e);
-    void watchpointDeferred(SpecEvent e);
-    void watchpointDeleted(SpecEvent e);
-    void watchpointResolved(SpecEvent e);
-    void watchpointError(SpecErrorEvent e);
-
-    void exceptionInterceptSet(SpecEvent e);
-    void exceptionInterceptDeferred(SpecEvent e);
-    void exceptionInterceptDeleted(SpecEvent e);
-    void exceptionInterceptResolved(SpecEvent e);
-    void exceptionInterceptError(SpecErrorEvent e);
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java
deleted file mode 100644
index dd8b0cb3f7e..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadGroupIterator.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.ThreadGroupReference;
-import java.util.List;
-import java.util.Stack;
-import java.util.ArrayList;
-import java.util.Iterator;
-
-/**
- * Descend the tree of thread groups.
- * @author Robert G. Field
- */
-public class ThreadGroupIterator implements Iterator {
-    private final Stack> stack
-                        = new Stack>();
-
-    public ThreadGroupIterator(List tgl) {
-        push(tgl);
-    }
-
-    public ThreadGroupIterator(ThreadGroupReference tg) {
-        List tgl = new ArrayList();
-        tgl.add(tg);
-        push(tgl);
-    }
-
-/*
-    ThreadGroupIterator() {
-        this(Env.vm().topLevelThreadGroups());
-    }
-*/
-
-    private Iterator top() {
-        return stack.peek();
-    }
-
-    /**
-     * The invariant in this class is that the top iterator
-     * on the stack has more elements.  If the stack is
-     * empty, there is no top.  This method assures
-     * this invariant.
-     */
-    private void push(List tgl) {
-        stack.push(tgl.iterator());
-        while (!stack.isEmpty() && !top().hasNext()) {
-            stack.pop();
-        }
-    }
-
-    @Override
-    public boolean hasNext() {
-        return !stack.isEmpty();
-    }
-
-    @Override
-    public ThreadGroupReference next() {
-        return nextThreadGroup();
-    }
-
-    public ThreadGroupReference nextThreadGroup() {
-        ThreadGroupReference tg = top().next();
-        push(tg.threadGroups());
-        return tg;
-    }
-
-    @Override
-    public void remove() {
-        throw new UnsupportedOperationException();
-    }
-
-/*
-    static ThreadGroupReference find(String name) {
-        ThreadGroupIterator tgi = new ThreadGroupIterator();
-        while (tgi.hasNext()) {
-            ThreadGroupReference tg = tgi.nextThreadGroup();
-            if (tg.name().equals(name)) {
-                return tg;
-            }
-        }
-        return null;
-    }
-*/
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadInfo.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadInfo.java
deleted file mode 100644
index 02626ac324f..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadInfo.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.*;
-
-//### Should handle target VM death or connection failure cleanly.
-
-public class ThreadInfo {
-
-    private ThreadReference thread;
-    private int status;
-
-    private int frameCount;
-
-    Object userObject;  // User-supplied annotation.
-
-    private boolean interrupted = false;
-
-    private void assureInterrupted() throws VMNotInterruptedException {
-        if (!interrupted) {
-            throw new VMNotInterruptedException();
-        }
-    }
-
-    ThreadInfo (ThreadReference thread) {
-        this.thread = thread;
-        this.frameCount = -1;
-    }
-
-    public ThreadReference thread() {
-        return thread;
-    }
-
-    public int getStatus() throws VMNotInterruptedException {
-        assureInterrupted();
-        update();
-        return status;
-    }
-
-    public int getFrameCount() throws VMNotInterruptedException {
-        assureInterrupted();
-        update();
-        return frameCount;
-    }
-
-    public StackFrame getFrame(int index) throws VMNotInterruptedException {
-        assureInterrupted();
-        update();
-        try {
-            return thread.frame(index);
-        } catch (IncompatibleThreadStateException e) {
-            // Should not happen
-            interrupted = false;
-            throw new VMNotInterruptedException();
-        }
-    }
-
-    public Object getUserObject() {
-        return userObject;
-    }
-
-    public void setUserObject(Object obj) {
-        userObject = obj;
-    }
-
-    // Refresh upon first access after cache is cleared.
-
-    void update() throws VMNotInterruptedException {
-        if (frameCount == -1) {
-            try {
-                status = thread.status();
-                frameCount = thread.frameCount();
-            } catch (IncompatibleThreadStateException e) {
-                // Should not happen
-                interrupted = false;
-                throw new VMNotInterruptedException();
-            }
-        }
-    }
-
-    // Called from 'ExecutionManager'.
-
-    void validate() {
-        interrupted = true;
-    }
-
-    void invalidate() {
-        interrupted = false;
-        frameCount = -1;
-        status = ThreadReference.THREAD_STATUS_UNKNOWN;
-    }
-
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadIterator.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadIterator.java
deleted file mode 100644
index b82d88e6e1e..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ThreadIterator.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-import com.sun.jdi.ThreadGroupReference;
-import com.sun.jdi.ThreadReference;
-import java.util.List;
-import java.util.Iterator;
-
-public class ThreadIterator implements Iterator {
-    Iterator it = null;
-    ThreadGroupIterator tgi;
-
-    public ThreadIterator(ThreadGroupReference tg) {
-        tgi = new ThreadGroupIterator(tg);
-    }
-
-    //### make this package access only?
-    public ThreadIterator(List tgl) {
-        tgi = new ThreadGroupIterator(tgl);
-    }
-
-    @Override
-    public boolean hasNext() {
-        while (it == null || !it.hasNext()) {
-            if (!tgi.hasNext()) {
-                return false; // no more
-            }
-            it = tgi.nextThreadGroup().threads().iterator();
-        }
-        return true;
-    }
-
-    @Override
-    public ThreadReference next() {
-        return it.next();
-    }
-
-    public ThreadReference nextThread() {
-        return next();
-    }
-
-    @Override
-    public void remove() {
-        throw new UnsupportedOperationException();
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Utils.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Utils.java
deleted file mode 100644
index 34f1d724929..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/Utils.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;   //### does it belong here?
-
-import com.sun.jdi.*;
-
-public class Utils {
-
-    /**
-     * Return the thread status description.
-     */
-    public static String getStatus(ThreadReference thr) {
-        int status = thr.status();
-        String result;
-        switch (status) {
-          case ThreadReference.THREAD_STATUS_UNKNOWN:
-            result = "unknown status";
-            break;
-          case ThreadReference.THREAD_STATUS_ZOMBIE:
-            result = "zombie";
-            break;
-          case ThreadReference.THREAD_STATUS_RUNNING:
-            result = "running";
-            break;
-          case ThreadReference.THREAD_STATUS_SLEEPING:
-            result = "sleeping";
-            break;
-          case ThreadReference.THREAD_STATUS_MONITOR:
-            result = "waiting to acquire a monitor lock";
-            break;
-          case ThreadReference.THREAD_STATUS_WAIT:
-            result = "waiting on a condition";
-            break;
-          default:
-            result = "";
-        }
-        if (thr.isSuspended()) {
-            result += " (suspended)";
-        }
-        return result;
-    }
-
-    /**
-     * Return a description of an object.
-     */
-    public static String description(ObjectReference ref) {
-        ReferenceType clazz = ref.referenceType();
-        long id = ref.uniqueID();  //### TODO use real id
-        if (clazz == null) {
-            return toHex(id);
-        } else {
-            return "(" + clazz.name() + ")" + toHex(id);
-        }
-    }
-
-    /**
-     * Convert a long to a hexadecimal string.
-     */
-    public static String toHex(long n) {
-        char s1[] = new char[16];
-        char s2[] = new char[18];
-
-        // Store digits in reverse order.
-        int i = 0;
-        do {
-            long d = n & 0xf;
-            s1[i++] = (char)((d < 10) ? ('0' + d) : ('a' + d - 10));
-        } while ((n >>>= 4) > 0);
-
-        // Now reverse the array.
-        s2[0] = '0';
-        s2[1] = 'x';
-        int j = 2;
-        while (--i >= 0) {
-            s2[j++] = s1[i];
-        }
-        return new String(s2, 0, j);
-    }
-
-    /**
-     * Convert hexadecimal strings to longs.
-     */
-    public static long fromHex(String hexStr) {
-        String str = hexStr.startsWith("0x") ?
-            hexStr.substring(2).toLowerCase() : hexStr.toLowerCase();
-        if (hexStr.length() == 0) {
-            throw new NumberFormatException();
-        }
-
-        long ret = 0;
-        for (int i = 0; i < str.length(); i++) {
-            int c = str.charAt(i);
-            if (c >= '0' && c <= '9') {
-                ret = (ret * 16) + (c - '0');
-            } else if (c >= 'a' && c <= 'f') {
-                ret = (ret * 16) + (c - 'a' + 10);
-            } else {
-                throw new NumberFormatException();
-            }
-        }
-        return ret;
-    }
-
-
-    /*
-     * The next two methods are used by this class and by EventHandler
-     * to print consistent locations and error messages.
-     */
-    public static String locationString(Location loc) {
-        return  loc.declaringType().name() +
-            "." + loc.method().name() + "(), line=" +
-            loc.lineNumber();
-    }
-
-//### UNUSED.
-/************************
-    private String typedName(Method method) {
-        // TO DO: Use method.signature() instead of method.arguments() so that
-        // we get sensible results for classes without debugging info
-        StringBuffer buf = new StringBuffer();
-        buf.append(method.name());
-        buf.append("(");
-        Iterator it = method.arguments().iterator();
-        while (it.hasNext()) {
-            buf.append(((LocalVariable)it.next()).typeName());
-            if (it.hasNext()) {
-                buf.append(",");
-            }
-        }
-        buf.append(")");
-        return buf.toString();
-    }
-************************/
-
-    public static boolean isValidMethodName(String s) {
-        return isJavaIdentifier(s) ||
-               s.equals("") ||
-               s.equals("");
-    }
-
-    public static boolean isJavaIdentifier(String s) {
-        if (s.length() == 0) {
-            return false;
-        }
-        int cp = s.codePointAt(0);
-        if (! Character.isJavaIdentifierStart(cp)) {
-            return false;
-        }
-        for (int i = Character.charCount(cp); i < s.length(); i += Character.charCount(cp)) {
-            cp = s.codePointAt(i);
-            if (! Character.isJavaIdentifierPart(cp)) {
-                return false;
-            }
-        }
-        return true;
-    }
-
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMLaunchFailureException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMLaunchFailureException.java
deleted file mode 100644
index c2429684d29..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMLaunchFailureException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-public class VMLaunchFailureException extends Exception {
-
-    private static final long serialVersionUID = -2439646729274310108L;
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMNotInterruptedException.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMNotInterruptedException.java
deleted file mode 100644
index 489d88086cb..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/VMNotInterruptedException.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-public class VMNotInterruptedException extends Exception {
-
-    private static final long serialVersionUID = 8111074582188765600L;
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/WatchpointSpec.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/WatchpointSpec.java
deleted file mode 100644
index 367e38c7490..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/WatchpointSpec.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.bdi;
-
-public abstract class WatchpointSpec extends EventRequestSpec {
-    final String fieldId;
-
-    WatchpointSpec(EventRequestSpecList specs,
-                   ReferenceTypeSpec refSpec, String fieldId) {
-        super(specs, refSpec);
-        this.fieldId = fieldId;
-//        if (!isJavaIdentifier(fieldId)) {
-//            throw new MalformedMemberNameException(fieldId);
-//        }
-    }
-
-    @Override
-    void notifySet(SpecListener listener, SpecEvent evt) {
-        listener.watchpointSet(evt);
-    }
-
-    @Override
-    void notifyDeferred(SpecListener listener, SpecEvent evt) {
-        listener.watchpointDeferred(evt);
-    }
-
-    @Override
-    void notifyResolved(SpecListener listener, SpecEvent evt) {
-        listener.watchpointResolved(evt);
-    }
-
-    @Override
-    void notifyDeleted(SpecListener listener, SpecEvent evt) {
-        listener.watchpointDeleted(evt);
-    }
-
-    @Override
-    void notifyError(SpecListener listener, SpecErrorEvent evt) {
-        listener.watchpointError(evt);
-    }
-
-    @Override
-    public int hashCode() {
-        return refSpec.hashCode() + fieldId.hashCode() +
-            getClass().hashCode();
-    }
-
-    @Override
-    public boolean equals(Object obj) {
-        if (obj instanceof WatchpointSpec) {
-            WatchpointSpec watchpoint = (WatchpointSpec)obj;
-
-            return fieldId.equals(watchpoint.fieldId) &&
-                   refSpec.equals(watchpoint.refSpec) &&
-                   getClass().equals(watchpoint.getClass());
-        } else {
-            return false;
-        }
-    }
-
-    @Override
-    public String errorMessageFor(Exception e) {
-        if (e instanceof NoSuchFieldException) {
-            return ("No field " + fieldId + " in " + refSpec);
-        } else {
-            return super.errorMessageFor(e);
-        }
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AbstractEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AbstractEventSet.java
deleted file mode 100644
index 0a82f15ee0a..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AbstractEventSet.java
+++ /dev/null
@@ -1,272 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.event;
-
-import com.sun.jdi.*;
-import com.sun.jdi.event.*;
-import com.sun.jdi.request.*;
-
-import java.util.*;
-
-public abstract class AbstractEventSet extends EventObject implements EventSet {
-
-    private static final long serialVersionUID = 2772717574222076977L;
-    private final EventSet jdiEventSet;
-    final Event oneEvent;
-
-    /**
-     */
-    AbstractEventSet(EventSet jdiEventSet) {
-        super(jdiEventSet.virtualMachine());
-        this.jdiEventSet = jdiEventSet;
-        this.oneEvent = eventIterator().nextEvent();
-    }
-
-    public static AbstractEventSet toSpecificEventSet(EventSet jdiEventSet) {
-        Event evt = jdiEventSet.eventIterator().nextEvent();
-        if (evt instanceof LocatableEvent) {
-            if (evt instanceof ExceptionEvent) {
-                return new ExceptionEventSet(jdiEventSet);
-            } else if (evt instanceof WatchpointEvent) {
-                if (evt instanceof AccessWatchpointEvent) {
-                    return new AccessWatchpointEventSet(jdiEventSet);
-                } else {
-                    return new ModificationWatchpointEventSet(jdiEventSet);
-                }
-            } else {
-                return new LocationTriggerEventSet(jdiEventSet);
-            }
-        } else if (evt instanceof ClassPrepareEvent) {
-            return new ClassPrepareEventSet(jdiEventSet);
-        } else if (evt instanceof ClassUnloadEvent) {
-            return new ClassUnloadEventSet(jdiEventSet);
-        } else if (evt instanceof ThreadDeathEvent) {
-            return new ThreadDeathEventSet(jdiEventSet);
-        } else if (evt instanceof ThreadStartEvent) {
-            return new ThreadStartEventSet(jdiEventSet);
-        } else if (evt instanceof VMDeathEvent) {
-            return new VMDeathEventSet(jdiEventSet);
-        } else if (evt instanceof VMDisconnectEvent) {
-            return new VMDisconnectEventSet(jdiEventSet);
-        } else if (evt instanceof VMStartEvent) {
-            return new VMStartEventSet(jdiEventSet);
-        } else {
-            throw new IllegalArgumentException("Unknown event " + evt);
-        }
-    }
-
-    public abstract void notify(JDIListener listener);
-
-    // Implement Mirror
-
-    @Override
-    public VirtualMachine virtualMachine() {
-        return jdiEventSet.virtualMachine();
-    }
-
-    public VirtualMachine getVirtualMachine() {
-        return jdiEventSet.virtualMachine();
-    }
-
-    // Implement EventSet
-
-    /**
-     * Returns the policy used to suspend threads in the target VM
-     * for this event set. This policy is selected from the suspend
-     * policies for each event's request. The one that suspends the
-     * most threads is chosen when the event occurs in the target VM
-     * and that policy is returned here. See
-     * com.sun.jdi.request.EventRequest for the possible policy values.
-     *
-     * @return the integer suspendPolicy
-     */
-    public int getSuspendPolicy() {
-        return jdiEventSet.suspendPolicy();
-    }
-
-    @Override
-    public void resume() {
-        jdiEventSet.resume();
-    }
-
-    @Override
-    public int suspendPolicy() {
-        return jdiEventSet.suspendPolicy();
-    }
-
-    public boolean suspendedAll() {
-        return jdiEventSet.suspendPolicy() == EventRequest.SUSPEND_ALL;
-    }
-
-    public boolean suspendedEventThread() {
-        return jdiEventSet.suspendPolicy() == EventRequest.SUSPEND_EVENT_THREAD;
-    }
-
-    public boolean suspendedNone() {
-        return jdiEventSet.suspendPolicy() == EventRequest.SUSPEND_NONE;
-    }
-
-    /**
-     * Return an iterator specific to {@link Event} objects.
-     */
-    @Override
-    public EventIterator eventIterator() {
-        return jdiEventSet.eventIterator();
-    }
-
-
-    // Implement java.util.Set (by pass through)
-
-    /**
-     * Returns the number of elements in this set (its cardinality).  If this
-     * set contains more than Integer.MAX_VALUE elements, returns
-     * Integer.MAX_VALUE.
-     *
-     * @return the number of elements in this set (its cardinality).
-     */
-    @Override
-    public int size() {
-        return jdiEventSet.size();
-    }
-
-    /**
-     * Returns true if this set contains no elements.
-     *
-     * @return true if this set contains no elements.
-     */
-    @Override
-    public boolean isEmpty() {
-        return jdiEventSet.isEmpty();
-    }
-
-    /**
-     * Returns true if this set contains the specified element.  More
-     * formally, returns true if and only if this set contains an
-     * element e such that (o==null ? e==null :
-     * o.equals(e)).
-     *
-     * @return true if this set contains the specified element.
-     */
-    @Override
-    public boolean contains(Object o) {
-        return jdiEventSet.contains(o);
-    }
-
-    /**
-     * Returns an iterator over the elements in this set.  The elements are
-     * returned in no particular order (unless this set is an instance of some
-     * class that provides a guarantee).
-     *
-     * @return an iterator over the elements in this set.
-     */
-    @Override
-    public Iterator iterator() {
-        return jdiEventSet.iterator();
-    }
-
-    /**
-     * Returns an array containing all of the elements in this set.
-     * Obeys the general contract of the Collection.toArray method.
-     *
-     * @return an array containing all of the elements in this set.
-     */
-    @Override
-    public Object[] toArray() {
-        return jdiEventSet.toArray();
-    }
-
-    /**
-     * Returns an array containing all of the elements in this set whose
-     * runtime type is that of the specified array.  Obeys the general
-     * contract of the Collection.toArray(Object[]) method.
-     *
-     * @param a the array into which the elements of this set are to
-     *          be stored, if it is big enough {
-        return jdiEventSet.XXX();
-    } otherwise, a new array of the
-     *          same runtime type is allocated for this purpose.
-     * @return an array containing the elements of this set.
-     * @throws    ArrayStoreException the runtime type of a is not a supertype
-     * of the runtime type of every element in this set.
-     */
-    @Override
-    public  T[] toArray(T a[]) {
-        return jdiEventSet.toArray(a);
-    }
-
-    // Bulk Operations
-
-    /**
-     * Returns true if this set contains all of the elements of the
-     * specified collection.  If the specified collection is also a set, this
-     * method returns true if it is a subset of this set.
-     *
-     * @param c collection to be checked for containment in this set.
-     * @return true if this set contains all of the elements of the
-     *         specified collection.
-     */
-    @Override
-    public boolean containsAll(Collection c) {
-        return jdiEventSet.containsAll(c);
-    }
-
-
-    // Make the rest of Set unmodifiable
-
-    @Override
-    public boolean add(Event e){
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public boolean remove(Object o) {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public boolean addAll(Collection coll) {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public boolean removeAll(Collection coll) {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public boolean retainAll(Collection coll) {
-        throw new UnsupportedOperationException();
-    }
-    @Override
-    public void clear() {
-        throw new UnsupportedOperationException();
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AccessWatchpointEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AccessWatchpointEventSet.java
deleted file mode 100644
index 10462e3bbb4..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/AccessWatchpointEventSet.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.event;
-
-import com.sun.jdi.event.*;
-
-public class AccessWatchpointEventSet extends WatchpointEventSet {
-
-    private static final long serialVersionUID = -2620394219156607673L;
-
-    AccessWatchpointEventSet(EventSet jdiEventSet) {
-        super(jdiEventSet);
-    }
-
-    @Override
-    public void notify(JDIListener listener) {
-        listener.accessWatchpoint(this);
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassPrepareEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassPrepareEventSet.java
deleted file mode 100644
index 9010415e362..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassPrepareEventSet.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.event;
-
-import com.sun.jdi.*;
-import com.sun.jdi.event.*;
-
-public class ClassPrepareEventSet extends AbstractEventSet {
-
-    private static final long serialVersionUID = 5958493423581010491L;
-
-    ClassPrepareEventSet(EventSet jdiEventSet) {
-        super(jdiEventSet);
-    }
-
-    /**
-     * Returns the thread in which this event has occurred.
-     *
-     * @return a {@link ThreadReference} which mirrors the event's thread in
-     * the target VM.
-     */
-    public ThreadReference getThread() {
-        return ((ClassPrepareEvent)oneEvent).thread();
-    }
-
-
-    /**
-     * Returns the reference type for which this event was generated.
-     *
-     * @return a {@link ReferenceType} which mirrors the class, interface, or
-     * array which has been linked.
-     */
-    public ReferenceType getReferenceType() {
-        return ((ClassPrepareEvent)oneEvent).referenceType();
-    }
-
-    @Override
-    public void notify(JDIListener listener) {
-        listener.classPrepare(this);
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassUnloadEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassUnloadEventSet.java
deleted file mode 100644
index ad57b70d059..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ClassUnloadEventSet.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.event;
-
-import com.sun.jdi.event.*;
-
-public class ClassUnloadEventSet extends AbstractEventSet {
-
-    private static final long serialVersionUID = 8370341450345835866L;
-
-    ClassUnloadEventSet(EventSet jdiEventSet) {
-        super(jdiEventSet);
-    }
-
-    /**
-     * Returns the name of the class that has been unloaded.
-     */
-    public String getClassName() {
-        return ((ClassUnloadEvent)oneEvent).className();
-    }
-
-    /**
-     * Returns the JNI-style signature of the class that has been unloaded.
-     */
-    public String getClassSignature() {
-        return ((ClassUnloadEvent)oneEvent).classSignature();
-    }
-
-    @Override
-    public void notify(JDIListener listener) {
-        listener.classUnload(this);
-    }
-}
diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ExceptionEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ExceptionEventSet.java
deleted file mode 100644
index d59cce74d49..00000000000
--- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ExceptionEventSet.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/*
- * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute 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.
- */
-
-/*
- * This source code is provided to illustrate the usage of a given feature
- * or technique and has been deliberately simplified. Additional steps
- * required for a production-quality application, such as security checks,
- * input validation and proper error handling, might not be present in
- * this sample code.
- */
-
-
-package com.sun.tools.example.debug.event;
-
-import com.sun.jdi.*;
-import com.sun.jdi.event.*;
-
-public class ExceptionEventSet extends LocatableEventSet {
-
-    private static final long serialVersionUID = 5328140167954640711L;
-
-    ExceptionEventSet(EventSet jdiEventSet) {
-        super(jdiEventSet);
-    }
-
-    /**
-     * Gets the thrown exception object. The exception object is
-     * an instance of java.lang.Throwable or a subclass in the
-     * target VM.
-     *
-     * @return an {@link ObjectReference} which mirrors the thrown object in
-     * the target VM.
-     */
-    public ObjectReference getException() {
-        return ((ExceptionEvent)oneEvent).exception();
-    }
-
-    /**
-     * Gets the location where the exception will be caught. An exception
-     * is considered to be caught if, at the point of the throw, the
-     * current location is dynamically enclosed in a try statement that
-     * handles the exception. (See the JVM specification for details).
-     * If there is such a try statement, the catch location is the
-     * first code index of the appropriate catch clause.
-     * 

- * If there are native methods in the call stack at the time of the - * exception, there are important restrictions to note about the - * returned catch location. In such cases, - * it is not possible to predict whether an exception will be handled - * by some native method on the call stack. - * Thus, it is possible that exceptions considered uncaught - * here will, in fact, be handled by a native method and not cause - * termination of the target VM. Also, it cannot be assumed that the - * catch location returned here will ever be reached by the throwing - * thread. If there is - * a native frame between the current location and the catch location, - * the exception might be handled and cleared in that native method - * instead. - * - * @return the {@link Location} where the exception will be caught or null if - * the exception is uncaught. - */ - public Location getCatchLocation() { - return ((ExceptionEvent)oneEvent).catchLocation(); - } - - @Override - public void notify(JDIListener listener) { - listener.exception(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIAdapter.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIAdapter.java deleted file mode 100644 index 056cd0933b5..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIAdapter.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -/** - * The adapter which receives JDI event sets. The methods in this - * class are empty; this class is provided as a convenience for - * easily creating listeners by extending this class and overriding - * only the methods of interest. - */ -public class JDIAdapter implements JDIListener { - - @Override - public void accessWatchpoint(AccessWatchpointEventSet e) { - } - - @Override - public void classPrepare(ClassPrepareEventSet e) { - } - - @Override - public void classUnload(ClassUnloadEventSet e) { - } - - @Override - public void exception(ExceptionEventSet e) { - } - - @Override - public void locationTrigger(LocationTriggerEventSet e) { - } - - @Override - public void modificationWatchpoint(ModificationWatchpointEventSet e) { - } - - @Override - public void threadDeath(ThreadDeathEventSet e) { - } - - @Override - public void threadStart(ThreadStartEventSet e) { - } - - @Override - public void vmDeath(VMDeathEventSet e) { - } - - @Override - public void vmDisconnect(VMDisconnectEventSet e) { - } - - @Override - public void vmStart(VMStartEventSet e) { - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIListener.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIListener.java deleted file mode 100644 index 18a37261ee4..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/JDIListener.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import java.util.EventListener; - -public interface JDIListener extends EventListener { - void accessWatchpoint(AccessWatchpointEventSet e); - void classPrepare(ClassPrepareEventSet e); - void classUnload(ClassUnloadEventSet e); - void exception(ExceptionEventSet e); - void locationTrigger(LocationTriggerEventSet e); - void modificationWatchpoint(ModificationWatchpointEventSet e); - void threadDeath(ThreadDeathEventSet e); - void threadStart(ThreadStartEventSet e); - void vmDeath(VMDeathEventSet e); - void vmDisconnect(VMDisconnectEventSet e); - void vmStart(VMStartEventSet e); -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/LocatableEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/LocatableEventSet.java deleted file mode 100644 index 6b4f607009c..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/LocatableEventSet.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -/** - * Abstract event set for events with location and thread. - */ -public abstract class LocatableEventSet extends AbstractEventSet { - - private static final long serialVersionUID = 1027131209997915620L; - - LocatableEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the {@link Location} of this mirror. Depending on context - * and on available debug information, this location will have - * varying precision. - * - * @return the {@link Location} of this mirror. - */ - public Location getLocation() { - return ((LocatableEvent)oneEvent).location(); - } - - /** - * Returns the thread in which this event has occurred. - * - * @return a {@link ThreadReference} which mirrors the event's thread in - * the target VM. - */ - public ThreadReference getThread() { - return ((LocatableEvent)oneEvent).thread(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ModificationWatchpointEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ModificationWatchpointEventSet.java deleted file mode 100644 index 41749efa705..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ModificationWatchpointEventSet.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public class ModificationWatchpointEventSet extends WatchpointEventSet { - - private static final long serialVersionUID = -680889300856154719L; - - ModificationWatchpointEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Value that will be assigned to the field when the instruction - * completes. - */ - public Value getValueToBe() { - return ((ModificationWatchpointEvent)oneEvent).valueToBe(); - } - - @Override - public void notify(JDIListener listener) { - listener.modificationWatchpoint(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadDeathEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadDeathEventSet.java deleted file mode 100644 index 893ec73fa97..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadDeathEventSet.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public class ThreadDeathEventSet extends AbstractEventSet { - - private static final long serialVersionUID = -8801604712308151331L; - - ThreadDeathEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the thread which is terminating. - * - * @return a {@link ThreadReference} which mirrors the event's thread in - * the target VM. - */ - public ThreadReference getThread() { - return ((ThreadDeathEvent)oneEvent).thread(); - } - - @Override - public void notify(JDIListener listener) { - listener.threadDeath(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadStartEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadStartEventSet.java deleted file mode 100644 index 657e9633c9c..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/ThreadStartEventSet.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public class ThreadStartEventSet extends AbstractEventSet { - - private static final long serialVersionUID = -3802096132294933502L; - - ThreadStartEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the thread which has started. - * - * @return a {@link ThreadReference} which mirrors the event's thread in - * the target VM. - */ - public ThreadReference getThread() { - return ((ThreadStartEvent)oneEvent).thread(); - } - - @Override - public void notify(JDIListener listener) { - listener.threadStart(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDeathEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDeathEventSet.java deleted file mode 100644 index b6f7eb31843..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDeathEventSet.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.event.*; - -public class VMDeathEventSet extends AbstractEventSet { - - private static final long serialVersionUID = 1163097303940092229L; - - VMDeathEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - @Override - public void notify(JDIListener listener) { - listener.vmDeath(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDisconnectEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDisconnectEventSet.java deleted file mode 100644 index 5b7dc7953ac..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMDisconnectEventSet.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.event.*; - -public class VMDisconnectEventSet extends AbstractEventSet { - - private static final long serialVersionUID = 7968123152344675342L; - - VMDisconnectEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - @Override - public void notify(JDIListener listener) { - listener.vmDisconnect(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMStartEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMStartEventSet.java deleted file mode 100644 index f9381239fc8..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/VMStartEventSet.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public class VMStartEventSet extends AbstractEventSet { - - private static final long serialVersionUID = -3384957227835478191L; - - VMStartEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the initial thread of the VM which has started. - * - * @return a {@link ThreadReference} which mirrors the event's - * thread in the target VM. - */ - public ThreadReference getThread() { - return ((VMStartEvent)oneEvent).thread(); - } - - @Override - public void notify(JDIListener listener) { - listener.vmStart(this); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/WatchpointEventSet.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/WatchpointEventSet.java deleted file mode 100644 index 76be4acf1da..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/event/WatchpointEventSet.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.event; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -public abstract class WatchpointEventSet extends LocatableEventSet { - - private static final long serialVersionUID = 5606285209703845409L; - - WatchpointEventSet(EventSet jdiEventSet) { - super(jdiEventSet); - } - - /** - * Returns the field that is about to be accessed/modified. - * - * @return a {@link Field} which mirrors the field - * in the target VM. - */ - public Field getField() { - return ((WatchpointEvent)oneEvent).field(); - } - - /** - * Returns the object whose field is about to be accessed/modified. - * Return null is the access is to a static field. - * - * @return a {@link ObjectReference} which mirrors the event's - * object in the target VM. - */ - public ObjectReference getObject() { - return ((WatchpointEvent)oneEvent).object(); - } - - /** - * Current value of the field. - */ - public Value getValueCurrent() { - return ((WatchpointEvent)oneEvent).valueCurrent(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ApplicationTool.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ApplicationTool.java deleted file mode 100644 index 717a5b9390e..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ApplicationTool.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import javax.swing.*; -import java.awt.*; -import java.awt.event.*; - -import com.sun.tools.example.debug.bdi.*; - -public class ApplicationTool extends JPanel { - - private static final long serialVersionUID = 310966063293205714L; - - private ExecutionManager runtime; - - private TypeScript script; - - private static final String PROMPT = "Input:"; - - public ApplicationTool(Environment env) { - - super(new BorderLayout()); - - this.runtime = env.getExecutionManager(); - - this.script = new TypeScript(PROMPT, false); // No implicit echo. - this.add(script); - - script.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - runtime.sendLineToApplication(script.readln()); - } - }); - - runtime.addApplicationEchoListener(new TypeScriptOutputListener(script)); - runtime.addApplicationOutputListener(new TypeScriptOutputListener(script)); - runtime.addApplicationErrorListener(new TypeScriptOutputListener(script)); - - //### should clean up on exit! - - } - - /****** - public void setFont(Font f) { - script.setFont(f); - } - ******/ - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassManager.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassManager.java deleted file mode 100644 index 6e347376769..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassManager.java +++ /dev/null @@ -1,73 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -public class ClassManager { - - // This class is provided primarily for symmetry with - // SourceManager. Currently, it does very little. - // If we add facilities in the future that require that - // class files be read outside of the VM, for example, to - // provide a disassembled view of a class for bytecode-level - // debugging, the required class file management will be done - // here. - - private SearchPath classPath; - - public ClassManager(Environment env) { - this.classPath = new SearchPath(""); - } - - public ClassManager(SearchPath classPath) { - this.classPath = classPath; - } - - /* - * Set path for access to class files. - */ - - public void setClassPath(SearchPath sp) { - classPath = sp; - } - - /* - * Get path for access to class files. - */ - - public SearchPath getClassPath() { - return classPath; - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassTreeTool.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassTreeTool.java deleted file mode 100644 index 995c414854c..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ClassTreeTool.java +++ /dev/null @@ -1,287 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.util.*; - -import javax.swing.*; -import javax.swing.tree.*; -import java.awt.*; -import java.awt.event.*; - -import com.sun.jdi.*; -import com.sun.tools.example.debug.event.*; -import com.sun.tools.example.debug.bdi.*; - -public class ClassTreeTool extends JPanel { - - private static final long serialVersionUID = 526178912591739259L; - - private Environment env; - - private ExecutionManager runtime; - private SourceManager sourceManager; - private ClassManager classManager; - - private JTree tree; - private DefaultTreeModel treeModel; - private ClassTreeNode root; -// private SearchPath sourcePath; - - private CommandInterpreter interpreter; - - private static String HEADING = "CLASSES"; - - public ClassTreeTool(Environment env) { - - super(new BorderLayout()); - - this.env = env; - this.runtime = env.getExecutionManager(); - this.sourceManager = env.getSourceManager(); - - this.interpreter = new CommandInterpreter(env); - - root = createClassTree(HEADING); - treeModel = new DefaultTreeModel(root); - - // Create a tree that allows one selection at a time. - - tree = new JTree(treeModel); - tree.setSelectionModel(new SingleLeafTreeSelectionModel()); - - /****** - // Listen for when the selection changes. - tree.addTreeSelectionListener(new TreeSelectionListener() { - public void valueChanged(TreeSelectionEvent e) { - ClassTreeNode node = (ClassTreeNode) - (e.getPath().getLastPathComponent()); - if (node != null) { - interpreter.executeCommand("view " + node.getReferenceTypeName()); - } - } - }); - ******/ - - MouseListener ml = new MouseAdapter() { - @Override - public void mouseClicked(MouseEvent e) { - int selRow = tree.getRowForLocation(e.getX(), e.getY()); - TreePath selPath = tree.getPathForLocation(e.getX(), e.getY()); - if(selRow != -1) { - if(e.getClickCount() == 1) { - ClassTreeNode node = - (ClassTreeNode)selPath.getLastPathComponent(); - // If user clicks on leaf, select it, and issue 'view' command. - if (node.isLeaf()) { - tree.setSelectionPath(selPath); - interpreter.executeCommand("view " + node.getReferenceTypeName()); - } - } - } - } - }; - tree.addMouseListener(ml); - - JScrollPane treeView = new JScrollPane(tree); - add(treeView); - - // Create listener. - ClassTreeToolListener listener = new ClassTreeToolListener(); - runtime.addJDIListener(listener); - runtime.addSessionListener(listener); - - //### remove listeners on exit! - } - - private class ClassTreeToolListener extends JDIAdapter - implements JDIListener, SessionListener { - - // SessionListener - - @Override - public void sessionStart(EventObject e) { - // Get system classes and any others loaded before attaching. - try { - for (ReferenceType type : runtime.allClasses()) { - root.addClass(type); - } - } catch (VMDisconnectedException ee) { - // VM terminated unexpectedly. - } catch (NoSessionException ee) { - // Ignore. Should not happen. - } - } - - @Override - public void sessionInterrupt(EventObject e) {} - @Override - public void sessionContinue(EventObject e) {} - - // JDIListener - - @Override - public void classPrepare(ClassPrepareEventSet e) { - root.addClass(e.getReferenceType()); - } - - @Override - public void classUnload(ClassUnloadEventSet e) { - root.removeClass(e.getClassName()); - } - - @Override - public void vmDisconnect(VMDisconnectEventSet e) { - // Clear contents of this view. - root = createClassTree(HEADING); - treeModel = new DefaultTreeModel(root); - tree.setModel(treeModel); - } - } - - ClassTreeNode createClassTree(String label) { - return new ClassTreeNode(label, null); - } - - class ClassTreeNode extends DefaultMutableTreeNode { - - private String name; - private ReferenceType refTy; // null for package - - ClassTreeNode(String name, ReferenceType refTy) { - this.name = name; - this.refTy = refTy; - } - - @Override - public String toString() { - return name; - } - - public ReferenceType getReferenceType() { - return refTy; - } - - public String getReferenceTypeName() { - return refTy.name(); - } - - private boolean isPackage() { - return (refTy == null); - } - - @Override - public boolean isLeaf() { - return !isPackage(); - } - - public void addClass(ReferenceType refTy) { - addClass(refTy.name(), refTy); - } - - private void addClass(String className, ReferenceType refTy) { - if (className.equals("")) { - return; - } - int pos = className.indexOf('.'); - if (pos < 0) { - insertNode(className, refTy); - } else { - String head = className.substring(0, pos); - String tail = className.substring(pos + 1); - ClassTreeNode child = insertNode(head, null); - child.addClass(tail, refTy); - } - } - - private ClassTreeNode insertNode(String name, ReferenceType refTy) { - for (int i = 0; i < getChildCount(); i++) { - ClassTreeNode child = (ClassTreeNode)getChildAt(i); - int cmp = name.compareTo(child.toString()); - if (cmp == 0) { - // like-named node already exists - return child; - } else if (cmp < 0) { - // insert new node before the child - ClassTreeNode newChild = new ClassTreeNode(name, refTy); - treeModel.insertNodeInto(newChild, this, i); - return newChild; - } - } - // insert new node after last child - ClassTreeNode newChild = new ClassTreeNode(name, refTy); - treeModel.insertNodeInto(newChild, this, getChildCount()); - return newChild; - } - - public void removeClass(String className) { - if (className.equals("")) { - return; - } - int pos = className.indexOf('.'); - if (pos < 0) { - ClassTreeNode child = findNode(className); - if (!isPackage()) { - treeModel.removeNodeFromParent(child); - } - } else { - String head = className.substring(0, pos); - String tail = className.substring(pos + 1); - ClassTreeNode child = findNode(head); - child.removeClass(tail); - if (isPackage() && child.getChildCount() < 1) { - // Prune non-leaf nodes with no children. - treeModel.removeNodeFromParent(child); - } - } - } - - private ClassTreeNode findNode(String name) { - for (int i = 0; i < getChildCount(); i++) { - ClassTreeNode child = (ClassTreeNode)getChildAt(i); - int cmp = name.compareTo(child.toString()); - if (cmp == 0) { - return child; - } else if (cmp > 0) { - // not found, since children are sorted - return null; - } - } - return null; - } - - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandInterpreter.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandInterpreter.java deleted file mode 100644 index fbff95b2703..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandInterpreter.java +++ /dev/null @@ -1,1468 +0,0 @@ -/* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.io.*; -import java.util.*; - -import com.sun.jdi.*; -import com.sun.tools.example.debug.bdi.*; - -public class CommandInterpreter { - - boolean echo; - - Environment env; - - private ContextManager context; - private ExecutionManager runtime; - private ClassManager classManager; - private SourceManager sourceManager; - - private OutputSink out; //### Hack! Should be local in each method used. - private String lastCommand = "help"; - - public CommandInterpreter(Environment env) { - this(env, true); - } - - public CommandInterpreter(Environment env, boolean echo) { - this.env = env; - this.echo = echo; - this.runtime = env.getExecutionManager(); - this.context = env.getContextManager(); - this.classManager = env.getClassManager(); - this.sourceManager = env.getSourceManager(); - } - - private ThreadReference[] threads = null; - - /* - * The numbering of threads is relative to the current set of threads, - * and may be affected by the creation and termination of new threads. - * Commands issued using such thread ids will only give reliable behavior - * relative to what was shown earlier in 'list' commands if the VM is interrupted. - * We need a better scheme. - */ - - private ThreadReference[] threads() throws NoSessionException { - if (threads == null) { - ThreadIterator ti = new ThreadIterator(getDefaultThreadGroup()); - List tlist = new ArrayList(); - while (ti.hasNext()) { - tlist.add(ti.nextThread()); - } - threads = tlist.toArray(new ThreadReference[tlist.size()]); - } - return threads; - } - - private ThreadReference findThread(String idToken) throws NoSessionException { - String id; - ThreadReference thread = null; - if (idToken.startsWith("t@")) { - id = idToken.substring(2); - } else { - id = idToken; - } - try { - ThreadReference[] threads = threads(); - long threadID = Long.parseLong(id, 16); - for (ThreadReference thread2 : threads) { - if (thread2.uniqueID() == threadID) { - thread = thread2; - break; - } - } - if (thread == null) { - //env.failure("No thread for id \"" + idToken + "\""); - env.failure("\"" + idToken + "\" is not a valid thread id."); - } - } catch (NumberFormatException e) { - env.error("Thread id \"" + idToken + "\" is ill-formed."); - thread = null; - } - return thread; - } - - private ThreadIterator allThreads() throws NoSessionException { - threads = null; - //### Why not use runtime.allThreads().iterator() ? - return new ThreadIterator(runtime.topLevelThreadGroups()); - } - - private ThreadIterator currentThreadGroupThreads() throws NoSessionException { - threads = null; - return new ThreadIterator(getDefaultThreadGroup()); - } - - private ThreadGroupIterator allThreadGroups() throws NoSessionException { - threads = null; - return new ThreadGroupIterator(runtime.topLevelThreadGroups()); - } - - private ThreadGroupReference defaultThreadGroup; - - private ThreadGroupReference getDefaultThreadGroup() throws NoSessionException { - if (defaultThreadGroup == null) { - defaultThreadGroup = runtime.systemThreadGroup(); - } - return defaultThreadGroup; - } - - private void setDefaultThreadGroup(ThreadGroupReference tg) { - defaultThreadGroup = tg; - } - - /* - * Command handlers. - */ - - // Command: classes - - private void commandClasses() throws NoSessionException { - OutputSink out = env.getOutputSink(); - //out.println("** classes list **"); - for (ReferenceType refType : runtime.allClasses()) { - out.println(refType.name()); - } - out.show(); - } - - - // Command: methods - - private void commandMethods(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("No class specified."); - return; - } - String idClass = t.nextToken(); - ReferenceType cls = findClass(idClass); - if (cls != null) { - List methods = cls.allMethods(); - OutputSink out = env.getOutputSink(); - for (int i = 0; i < methods.size(); i++) { - Method method = methods.get(i); - out.print(method.declaringType().name() + " " + - method.name() + "("); - Iterator it = method.argumentTypeNames().iterator(); - if (it.hasNext()) { - while (true) { - out.print(it.next()); - if (!it.hasNext()) { - break; - } - out.print(", "); - } - } - out.println(")"); - } - out.show(); - } else { - //### Should validate class name syntax. - env.failure("\"" + idClass + "\" is not a valid id or class name."); - } - } - - private ReferenceType findClass(String pattern) throws NoSessionException { - List results = runtime.findClassesMatchingPattern(pattern); - if (results.size() > 0) { - //### Should handle multiple results sensibly. - return results.get(0); - } - return null; - } - - // Command: threads - - private void commandThreads(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - OutputSink out = env.getOutputSink(); - printThreadGroup(out, getDefaultThreadGroup(), 0); - out.show(); - return; - } - String name = t.nextToken(); - ThreadGroupReference tg = findThreadGroup(name); - if (tg == null) { - env.failure(name + " is not a valid threadgroup name."); - } else { - OutputSink out = env.getOutputSink(); - printThreadGroup(out, tg, 0); - out.show(); - } - } - - private ThreadGroupReference findThreadGroup(String name) throws NoSessionException { - //### Issue: Uniqueness of thread group names is not enforced. - ThreadGroupIterator tgi = allThreadGroups(); - while (tgi.hasNext()) { - ThreadGroupReference tg = tgi.nextThreadGroup(); - if (tg.name().equals(name)) { - return tg; - } - } - return null; - } - - private int printThreadGroup(OutputSink out, ThreadGroupReference tg, int iThread) { - out.println("Group " + tg.name() + ":"); - List tlist = tg.threads(); - int maxId = 0; - int maxName = 0; - for (int i = 0 ; i < tlist.size() ; i++) { - ThreadReference thr = tlist.get(i); - int len = Utils.description(thr).length(); - if (len > maxId) { - maxId = len; - } - String name = thr.name(); - int iDot = name.lastIndexOf('.'); - if (iDot >= 0 && name.length() > iDot) { - name = name.substring(iDot + 1); - } - if (name.length() > maxName) { - maxName = name.length(); - } - } - String maxNumString = String.valueOf(iThread + tlist.size()); - int maxNumDigits = maxNumString.length(); - for (int i = 0 ; i < tlist.size() ; i++) { - ThreadReference thr = tlist.get(i); - char buf[] = new char[80]; - for (int j = 0; j < 79; j++) { - buf[j] = ' '; - } - buf[79] = '\0'; - StringBuilder sbOut = new StringBuilder(); - sbOut.append(buf); - - // Right-justify the thread number at start of output string - String numString = String.valueOf(iThread + i + 1); - sbOut.insert(maxNumDigits - numString.length(), - numString); - sbOut.insert(maxNumDigits, "."); - - int iBuf = maxNumDigits + 2; - sbOut.insert(iBuf, Utils.description(thr)); - iBuf += maxId + 1; - String name = thr.name(); - int iDot = name.lastIndexOf('.'); - if (iDot >= 0 && name.length() > iDot) { - name = name.substring(iDot + 1); - } - sbOut.insert(iBuf, name); - iBuf += maxName + 1; - sbOut.insert(iBuf, Utils.getStatus(thr)); - sbOut.setLength(79); - out.println(sbOut.toString()); - } - for (ThreadGroupReference tg0 : tg.threadGroups()) { - if (!tg.equals(tg0)) { // TODO ref mgt - iThread += printThreadGroup(out, tg0, iThread + tlist.size()); - } - } - return tlist.size(); - } - - // Command: threadgroups - - private void commandThreadGroups() throws NoSessionException { - ThreadGroupIterator it = allThreadGroups(); - int cnt = 0; - OutputSink out = env.getOutputSink(); - while (it.hasNext()) { - ThreadGroupReference tg = it.nextThreadGroup(); - ++cnt; - out.println("" + cnt + ". " + Utils.description(tg) + " " + tg.name()); - } - out.show(); - } - - // Command: thread - - private void commandThread(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("Thread number not specified."); - return; - } - ThreadReference thread = findThread(t.nextToken()); - if (thread != null) { - //### Should notify user. - context.setCurrentThread(thread); - } - } - - // Command: threadgroup - - private void commandThreadGroup(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("Threadgroup name not specified."); - return; - } - String name = t.nextToken(); - ThreadGroupReference tg = findThreadGroup(name); - if (tg == null) { - env.failure(name + " is not a valid threadgroup name."); - } else { - //### Should notify user. - setDefaultThreadGroup(tg); - } - } - - // Command: run - - private void commandRun(StringTokenizer t) throws NoSessionException { - if (doLoad(false, t)) { - env.notice("Running ..."); - } - } - - // Command: load - - private void commandLoad(StringTokenizer t) throws NoSessionException { - if (doLoad(true, t)) {} - } - - private boolean doLoad(boolean suspended, - StringTokenizer t) throws NoSessionException { - - String clname; - - if (!t.hasMoreTokens()) { - clname = context.getMainClassName(); - if (!clname.equals("")) { - // Run from prevously-set class name. - try { - String vmArgs = context.getVmArguments(); - runtime.run(suspended, - vmArgs, - clname, - context.getProgramArguments()); - return true; - } catch (VMLaunchFailureException e) { - env.failure("Attempt to launch main class \"" + clname + "\" failed."); - } - } else { - env.failure("No main class specified and no current default defined."); - } - } else { - clname = t.nextToken(); - StringBuilder str = new StringBuilder(); - // Allow VM arguments to be specified here? - while (t.hasMoreTokens()) { - String tok = t.nextToken(); - str.append(tok); - if (t.hasMoreTokens()) { - str.append(' '); - } - } - String args = str.toString(); - try { - String vmArgs = context.getVmArguments(); - runtime.run(suspended, vmArgs, clname, args); - context.setMainClassName(clname); - //context.setVmArguments(vmArgs); - context.setProgramArguments(args); - return true; - } catch (VMLaunchFailureException e) { - env.failure("Attempt to launch main class \"" + clname + "\" failed."); - } - } - return false; - } - - // Command: connect - - private void commandConnect(StringTokenizer t) { - try { - LaunchTool.queryAndLaunchVM(runtime); - } catch (VMLaunchFailureException e) { - env.failure("Attempt to connect failed."); - } - } - - // Command: attach - - private void commandAttach(StringTokenizer t) { - String portName; - if (!t.hasMoreTokens()) { - portName = context.getRemotePort(); - if (!portName.equals("")) { - try { - runtime.attach(portName); - } catch (VMLaunchFailureException e) { - env.failure("Attempt to attach to port \"" + portName + "\" failed."); - } - } else { - env.failure("No port specified and no current default defined."); - } - } else { - portName = t.nextToken(); - try { - runtime.attach(portName); - } catch (VMLaunchFailureException e) { - env.failure("Attempt to attach to port \"" + portName + "\" failed."); - } - context.setRemotePort(portName); - } - } - - // Command: detach - - private void commandDetach(StringTokenizer t) throws NoSessionException { - runtime.detach(); - } - - // Command: interrupt - - private void commandInterrupt(StringTokenizer t) throws NoSessionException { - runtime.interrupt(); - } - - // Command: suspend - - private void commandSuspend(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - // Suspend all threads in the current thread group. - //### Issue: help message says default is all threads. - //### Behavior here agrees with 'jdb', however. - ThreadIterator ti = currentThreadGroupThreads(); - while (ti.hasNext()) { - // TODO - don't suspend debugger threads - ti.nextThread().suspend(); - } - env.notice("All (non-system) threads suspended."); - } else { - while (t.hasMoreTokens()) { - ThreadReference thread = findThread(t.nextToken()); - if (thread != null) { - //thread.suspend(); - runtime.suspendThread(thread); - } - } - } - } - - // Command: resume - - private void commandResume(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - // Suspend all threads in the current thread group. - //### Issue: help message says default is all threads. - //### Behavior here agrees with 'jdb', however. - ThreadIterator ti = currentThreadGroupThreads(); - while (ti.hasNext()) { - // TODO - don't suspend debugger threads - ti.nextThread().resume(); - } - env.notice("All threads resumed."); - } else { - while (t.hasMoreTokens()) { - ThreadReference thread = findThread(t.nextToken()); - if (thread != null) { - //thread.resume(); - runtime.resumeThread(thread); - } - } - } - } - - // Command: cont - - private void commandCont() throws NoSessionException { - try { - runtime.go(); - } catch (VMNotInterruptedException e) { - //### failure? - env.notice("Target VM is already running."); - } - } - - // Command: step - - private void commandStep(StringTokenizer t) throws NoSessionException{ - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - try { - if (t.hasMoreTokens() && - t.nextToken().toLowerCase().equals("up")) { - runtime.stepOut(current); - } else { - runtime.stepIntoLine(current); - } - } catch (AbsentInformationException e) { - env.failure("No linenumber information available -- " + - "Try \"stepi\" to step by instructions."); - } - } - - // Command: stepi - - private void commandStepi() throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - runtime.stepIntoInstruction(current); - } - - // Command: next - - private void commandNext() throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - try { - runtime.stepOverLine(current); - } catch (AbsentInformationException e) { - env.failure("No linenumber information available -- " + - "Try \"nexti\" to step by instructions."); - } - } - - // Command: nexti (NEW) - - private void commandNexti() throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - runtime.stepOverInstruction(current); - } - - // Command: kill - - private void commandKill(StringTokenizer t) throws NoSessionException { - //### Should change the way in which thread ids and threadgroup names - //### are distinguished. - if (!t.hasMoreTokens()) { - env.error("Usage: kill or "); - return; - } - while (t.hasMoreTokens()) { - String idToken = t.nextToken(); - ThreadReference thread = findThread(idToken); - if (thread != null) { - runtime.stopThread(thread); - env.notice("Thread " + thread.name() + " killed."); - return; - } else { - /* Check for threadgroup name, NOT skipping "system". */ - //### Should skip "system"? Classic 'jdb' does this. - //### Should deal with possible non-uniqueness of threadgroup names. - ThreadGroupIterator itg = allThreadGroups(); - while (itg.hasNext()) { - ThreadGroupReference tg = itg.nextThreadGroup(); - if (tg.name().equals(idToken)) { - ThreadIterator it = new ThreadIterator(tg); - while (it.hasNext()) { - runtime.stopThread(it.nextThread()); - } - env.notice("Threadgroup " + tg.name() + "killed."); - return; - } - } - env.failure("\"" + idToken + - "\" is not a valid threadgroup or id."); - } - } - } - - - /************* - // TODO - private void commandCatchException(StringTokenizer t) throws NoSessionException {} - // TODO - private void commandIgnoreException(StringTokenizer t) throws NoSessionException {} - *************/ - - // Command: up - - //### Print current frame after command? - - int readCount(StringTokenizer t) { - int cnt = 1; - if (t.hasMoreTokens()) { - String idToken = t.nextToken(); - try { - cnt = Integer.valueOf(idToken).intValue(); - } catch (NumberFormatException e) { - cnt = -1; - } - } - return cnt; - } - - void commandUp(StringTokenizer t) throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - int nLevels = readCount(t); - if (nLevels <= 0) { - env.error("usage: up [n frames]"); - return; - } - try { - int delta = context.moveCurrentFrameIndex(current, -nLevels); - if (delta == 0) { - env.notice("Already at top of stack."); - } else if (-delta < nLevels) { - env.notice("Moved up " + delta + " frames to top of stack."); - } - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - } - } - - private void commandDown(StringTokenizer t) throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - int nLevels = readCount(t); - if (nLevels <= 0) { - env.error("usage: down [n frames]"); - return; - } - try { - int delta = context.moveCurrentFrameIndex(current, nLevels); - if (delta == 0) { - env.notice("Already at bottom of stack."); - } else if (delta < nLevels) { - env.notice("Moved down " + delta + " frames to bottom of stack."); - } - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - } - } - - // Command: frame - - private void commandFrame(StringTokenizer t) throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No current thread."); - return; - } - if (!t.hasMoreTokens()) { - env.error("usage: frame "); - return; - } - String idToken = t.nextToken(); - int n; - try { - n = Integer.valueOf(idToken).intValue(); - } catch (NumberFormatException e) { - n = 0; - } - if (n <= 0) { - env.error("use positive frame index"); - return; - } - try { - int delta = context.setCurrentFrameIndex(current, n); - if (delta == 0) { - env.notice("Frame unchanged."); - } else if (delta < 0) { - env.notice("Moved up " + -delta + " frames."); - } else { - env.notice("Moved down " + delta + " frames."); - } - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - } - } - - // Command: where - - //### Should we insist that VM be interrupted here? - //### There is an inconsistency between the 'where' command - //### and 'up' and 'down' in this respect. - - private void commandWhere(StringTokenizer t, boolean showPC) - throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (!t.hasMoreTokens()) { - if (current == null) { - env.error("No thread specified."); - return; - } - dumpStack(current, showPC); - } else { - String token = t.nextToken(); - if (token.toLowerCase().equals("all")) { - ThreadIterator it = allThreads(); - while (it.hasNext()) { - ThreadReference thread = it.next(); - out.println(thread.name() + ": "); - dumpStack(thread, showPC); - } - } else { - ThreadReference thread = findThread(t.nextToken()); - //### Do we want to set current thread here? - //### Should notify user of change. - if (thread != null) { - context.setCurrentThread(thread); - } - dumpStack(thread, showPC); - } - } - } - - private void dumpStack(ThreadReference thread, boolean showPC) { - //### Check for these. - //env.failure("Thread no longer exists."); - //env.failure("Target VM must be in interrupted state."); - //env.failure("Current thread isn't suspended."); - //### Should handle extremely long stack traces sensibly for user. - List stack = null; - try { - stack = thread.frames(); - } catch (IncompatibleThreadStateException e) { - env.failure("Thread is not suspended."); - } - //### Fix this! - //### Previously mishandled cases where thread was not current. - //### Now, prints all of the stack regardless of current frame. - int frameIndex = 0; - //int frameIndex = context.getCurrentFrameIndex(); - if (stack == null) { - env.failure("Thread is not running (no stack)."); - } else { - OutputSink out = env.getOutputSink(); - int nFrames = stack.size(); - for (int i = frameIndex; i < nFrames; i++) { - StackFrame frame = stack.get(i); - Location loc = frame.location(); - Method meth = loc.method(); - out.print(" [" + (i + 1) + "] "); - out.print(meth.declaringType().name()); - out.print('.'); - out.print(meth.name()); - out.print(" ("); - if (meth.isNative()) { - out.print("native method"); - } else if (loc.lineNumber() != -1) { - try { - out.print(loc.sourceName()); - } catch (AbsentInformationException e) { - out.print(""); - } - out.print(':'); - out.print(loc.lineNumber()); - } - out.print(')'); - if (showPC) { - long pc = loc.codeIndex(); - if (pc != -1) { - out.print(", pc = " + pc); - } - } - out.println(); - } - out.show(); - } - } - - private void listEventRequests() throws NoSessionException { - // Print set breakpoints - List specs = runtime.eventRequestSpecs(); - if (specs.isEmpty()) { - env.notice("No breakpoints/watchpoints/exceptions set."); - } else { - OutputSink out = env.getOutputSink(); - out.println("Current breakpoints/watchpoints/exceptions set:"); - for (EventRequestSpec bp : specs) { - out.println("\t" + bp); - } - out.show(); - } - } - - private BreakpointSpec parseBreakpointSpec(String bptSpec) { - StringTokenizer t = new StringTokenizer(bptSpec); - BreakpointSpec bpSpec = null; -// try { - String token = t.nextToken("@:( \t\n\r"); - // We can't use hasMoreTokens here because it will cause any leading - // paren to be lost. - String rest; - try { - rest = t.nextToken("").trim(); - } catch (NoSuchElementException e) { - rest = null; - } - if ((rest != null) && rest.startsWith("@")) { - t = new StringTokenizer(rest.substring(1)); - String sourceName = token; - String lineToken = t.nextToken(); - int lineNumber = Integer.valueOf(lineToken).intValue(); - if (t.hasMoreTokens()) { - return null; - } - bpSpec = runtime.createSourceLineBreakpoint(sourceName, - lineNumber); - } else if ((rest != null) && rest.startsWith(":")) { - t = new StringTokenizer(rest.substring(1)); - String classId = token; - String lineToken = t.nextToken(); - int lineNumber = Integer.valueOf(lineToken).intValue(); - if (t.hasMoreTokens()) { - return null; - } - bpSpec = runtime.createClassLineBreakpoint(classId, lineNumber); - } else { - // Try stripping method from class.method token. - int idot = token.lastIndexOf('.'); - if ( (idot <= 0) || /* No dot or dot in first char */ - (idot >= token.length() - 1) ) { /* dot in last char */ - return null; - } - String methodName = token.substring(idot + 1); - String classId = token.substring(0, idot); - List argumentList = null; - if (rest != null) { - if (!rest.startsWith("(") || !rest.endsWith(")")) { - //### Should throw exception with error message - //out.println("Invalid method specification: " - // + methodName + rest); - return null; - } - // Trim the parens - //### What about spaces in arglist? - rest = rest.substring(1, rest.length() - 1); - argumentList = new ArrayList(); - t = new StringTokenizer(rest, ","); - while (t.hasMoreTokens()) { - argumentList.add(t.nextToken()); - } - } - bpSpec = runtime.createMethodBreakpoint(classId, - methodName, - argumentList); - } -// } catch (Exception e) { -// env.error("Exception attempting to create breakpoint: " + e); -// return null; -// } - return bpSpec; - } - - private void commandStop(StringTokenizer t) throws NoSessionException { - String token; - - if (!t.hasMoreTokens()) { - listEventRequests(); - } else { - token = t.nextToken(); - // Ignore optional "at" or "in" token. - // Allowed for backward compatibility. - if (token.equals("at") || token.equals("in")) { - if (t.hasMoreTokens()) { - token = t.nextToken(); - } else { - env.error("Missing breakpoint specification."); - return; - } - } - BreakpointSpec bpSpec = parseBreakpointSpec(token); - if (bpSpec != null) { - //### Add sanity-checks for deferred breakpoint. - runtime.install(bpSpec); - } else { - env.error("Ill-formed breakpoint specification."); - } - } - } - - private void commandClear(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - // Print set breakpoints - listEventRequests(); - return; - } - //### need 'clear all' - BreakpointSpec bpSpec = parseBreakpointSpec(t.nextToken()); - if (bpSpec != null) { - List specs = runtime.eventRequestSpecs(); - - if (specs.isEmpty()) { - env.notice("No breakpoints set."); - } else { - List toDelete = new ArrayList(); - for (EventRequestSpec spec : specs) { - if (spec.equals(bpSpec)) { - toDelete.add(spec); - } - } - // The request used for matching should be found - if (toDelete.size() <= 1) { - env.notice("No matching breakpoint set."); - } - for (EventRequestSpec spec : toDelete) { - runtime.delete(spec); - } - } - } else { - env.error("Ill-formed breakpoint specification."); - } - } - - // Command: list - - private void commandList(StringTokenizer t) throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.error("No thread specified."); - return; - } - Location loc; - try { - StackFrame frame = context.getCurrentFrame(current); - if (frame == null) { - env.failure("Thread has not yet begun execution."); - return; - } - loc = frame.location(); - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - return; - } - SourceModel source = sourceManager.sourceForLocation(loc); - if (source == null) { - if (loc.method().isNative()) { - env.failure("Current method is native."); - return; - } - env.failure("No source available for " + Utils.locationString(loc) + "."); - return; - } - ReferenceType refType = loc.declaringType(); - int lineno = loc.lineNumber(); - if (t.hasMoreTokens()) { - String id = t.nextToken(); - // See if token is a line number. - try { - lineno = Integer.valueOf(id).intValue(); - } catch (NumberFormatException nfe) { - // It isn't -- see if it's a method name. - List meths = refType.methodsByName(id); - if (meths == null || meths.size() == 0) { - env.failure(id + - " is not a valid line number or " + - "method name for class " + - refType.name()); - return; - } else if (meths.size() > 1) { - env.failure(id + - " is an ambiguous method name in" + - refType.name()); - return; - } - loc = meths.get(0).location(); - lineno = loc.lineNumber(); - } - } - int startLine = (lineno > 4) ? lineno - 4 : 1; - int endLine = startLine + 9; - String sourceLine = source.sourceLine(lineno); - if (sourceLine == null) { - env.failure("" + - lineno + - " is an invalid line number for " + - refType.name()); - } else { - OutputSink out = env.getOutputSink(); - for (int i = startLine; i <= endLine; i++) { - sourceLine = source.sourceLine(i); - if (sourceLine == null) { - break; - } - out.print(i); - out.print("\t"); - if (i == lineno) { - out.print("=> "); - } else { - out.print(" "); - } - out.println(sourceLine); - } - out.show(); - } - } - - // Command: use - // Get or set the source file path list. - - private void commandUse(StringTokenizer t) { - if (!t.hasMoreTokens()) { - out.println(sourceManager.getSourcePath().asString()); - } else { - //### Should throw exception for invalid path. - //### E.g., vetoable property change. - sourceManager.setSourcePath(new SearchPath(t.nextToken())); - } - } - - // Command: sourcepath - // Get or set the source file path list. (Alternate to 'use'.) - - private void commandSourcepath(StringTokenizer t) { - if (!t.hasMoreTokens()) { - out.println(sourceManager.getSourcePath().asString()); - } else { - //### Should throw exception for invalid path. - //### E.g., vetoable property change. - sourceManager.setSourcePath(new SearchPath(t.nextToken())); - } - } - - // Command: classpath - // Get or set the class file path list. - - private void commandClasspath(StringTokenizer t) { - if (!t.hasMoreTokens()) { - out.println(classManager.getClassPath().asString()); - } else { - //### Should throw exception for invalid path. - //### E.g., vetoable property change. - classManager.setClassPath(new SearchPath(t.nextToken())); - } - } - - // Command: view - // Display source for source file or class. - - private void commandView(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("Argument required"); - } else { - String name = t.nextToken(); - if (name.endsWith(".java") || - name.indexOf(File.separatorChar) >= 0) { - env.viewSource(name); - } else { - //### JDI crashes taking line number for class. - /***** - ReferenceType cls = findClass(name); - if (cls != null) { - env.viewLocation(cls.location()); - } else { - env.failure("No such class"); - } - *****/ - String fileName = name.replace('.', File.separatorChar) + ".java"; - env.viewSource(fileName); - } - } - } - - // Command: locals - // Print all local variables in current stack frame. - - private void commandLocals() throws NoSessionException { - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No default thread specified: " + - "use the \"thread\" command first."); - return; - } - StackFrame frame; - try { - frame = context.getCurrentFrame(current); - if (frame == null) { - env.failure("Thread has not yet created any stack frames."); - return; - } - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - return; - } - - List vars; - try { - vars = frame.visibleVariables(); - if (vars == null || vars.size() == 0) { - env.failure("No local variables"); - return; - } - } catch (AbsentInformationException e) { - env.failure("Local variable information not available." + - " Compile with -g to generate variable information"); - return; - } - - OutputSink out = env.getOutputSink(); - out.println("Method arguments:"); - for (LocalVariable var : vars) { - if (var.isArgument()) { - printVar(out, var, frame); - } - } - out.println("Local variables:"); - for (LocalVariable var : vars) { - if (!var.isArgument()) { - printVar(out, var, frame); - } - } - out.show(); - return; - } - - /** - * Command: monitor - * Monitor an expression - */ - private void commandMonitor(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("Argument required"); - } else { - env.getMonitorListModel().add(t.nextToken("")); - } - } - - /** - * Command: unmonitor - * Unmonitor an expression - */ - private void commandUnmonitor(StringTokenizer t) throws NoSessionException { - if (!t.hasMoreTokens()) { - env.error("Argument required"); - } else { - env.getMonitorListModel().remove(t.nextToken("")); - } - } - - // Print a stack variable. - - private void printVar(OutputSink out, LocalVariable var, StackFrame frame) { - out.print(" " + var.name()); - if (var.isVisible(frame)) { - Value val = frame.getValue(var); - out.println(" = " + val.toString()); - } else { - out.println(" is not in scope"); - } - } - - // Command: print - // Evaluate an expression. - - private void commandPrint(StringTokenizer t, boolean dumpObject) throws NoSessionException { - if (!t.hasMoreTokens()) { - //### Probably confused if expresion contains whitespace. - env.error("No expression specified."); - return; - } - ThreadReference current = context.getCurrentThread(); - if (current == null) { - env.failure("No default thread specified: " + - "use the \"thread\" command first."); - return; - } - StackFrame frame; - try { - frame = context.getCurrentFrame(current); - if (frame == null) { - env.failure("Thread has not yet created any stack frames."); - return; - } - } catch (VMNotInterruptedException e) { - env.failure("Target VM must be in interrupted state."); - return; - } - while (t.hasMoreTokens()) { - String expr = t.nextToken(""); - Value val = null; - try { - val = runtime.evaluate(frame, expr); - } catch(Exception e) { - env.error("Exception: " + e); - //### Fix this! - } - if (val == null) { - return; // Error message already printed - } - OutputSink out = env.getOutputSink(); - if (dumpObject && (val instanceof ObjectReference) && - !(val instanceof StringReference)) { - ObjectReference obj = (ObjectReference)val; - ReferenceType refType = obj.referenceType(); - out.println(expr + " = " + val.toString() + " {"); - dump(out, obj, refType, refType); - out.println("}"); - } else { - out.println(expr + " = " + val.toString()); - } - out.show(); - } - } - - private void dump(OutputSink out, - ObjectReference obj, ReferenceType refType, - ReferenceType refTypeBase) { - for (Field field : refType.fields()) { - out.print(" "); - if (!refType.equals(refTypeBase)) { - out.print(refType.name() + "."); - } - out.print(field.name() + ": "); - Object o = obj.getValue(field); - out.println((o == null) ? "null" : o.toString()); // Bug ID 4374471 - } - if (refType instanceof ClassType) { - ClassType sup = ((ClassType)refType).superclass(); - if (sup != null) { - dump(out, obj, sup, refTypeBase); - } - } else if (refType instanceof InterfaceType) { - for (InterfaceType sup : ((InterfaceType)refType).superinterfaces()) { - dump(out, obj, sup, refTypeBase); - } - } - } - - /* - * Display help message. - */ - - private void help() { - out.println("** command list **"); - out.println("threads [threadgroup] -- list threads"); - out.println("thread -- set default thread"); - out.println("suspend [thread id(s)] -- suspend threads (default: all)"); - out.println("resume [thread id(s)] -- resume threads (default: all)"); - out.println("where [thread id] | all -- dump a thread's stack"); - out.println("wherei [thread id] | all -- dump a thread's stack, with pc info"); - out.println("threadgroups -- list threadgroups"); - out.println("threadgroup -- set current threadgroup\n"); -// out.println("print -- print value of expression"); - out.println("dump -- print all object information\n"); -// out.println("eval -- evaluate expression (same as print)"); - out.println("locals -- print all local variables in current stack frame\n"); - out.println("classes -- list currently known classes"); - out.println("methods -- list a class's methods\n"); - out.println("stop [in] .[(argument_type,...)] -- set a breakpoint in a method"); - out.println("stop [at] : -- set a breakpoint at a line"); - out.println("up [n frames] -- move up a thread's stack"); - out.println("down [n frames] -- move down a thread's stack"); - out.println("frame -- to a frame"); - out.println("clear .[(argument_type,...)] -- clear a breakpoint in a method"); - out.println("clear : -- clear a breakpoint at a line"); - out.println("clear -- list breakpoints"); - out.println("step -- execute current line"); - out.println("step up -- execute until the current method returns to its caller"); - out.println("stepi -- execute current instruction"); - out.println("next -- step one line (step OVER calls)"); - out.println("nexti -- step one instruction (step OVER calls)"); - out.println("cont -- continue execution from breakpoint\n"); -// out.println("catch -- break for the specified exception"); -// out.println("ignore -- ignore when the specified exception\n"); - out.println("view classname|filename -- display source file"); - out.println("list [line number|method] -- print source code context at line or method"); - out.println("use -- display or change the source path\n"); -//### new - out.println("sourcepath -- display or change the source path\n"); -//### new - out.println("classpath -- display or change the class path\n"); - out.println("monitor -- evaluate an expression each time the program stops\n"); - out.println("unmonitor -- delete a monitor\n"); - out.println("read -- read and execute a command file\n"); -// out.println("memory -- report memory usage"); -// out.println("gc -- free unused objects\n"); - out.println("run [args] -- start execution of a Java class"); - out.println("run -- re-execute last class run"); - out.println("load [args] -- start execution of a Java class, initially suspended"); - out.println("load -- re-execute last class run, initially suspended"); - out.println("attach -- debug existing process\n"); - out.println("detach -- detach from debuggee process\n"); - out.println("kill -- kill a thread or threadgroup\n"); - out.println("!! -- repeat last command"); - out.println("help (or ?) -- list commands"); - out.println("exit (or quit) -- exit debugger"); - } - - /* - * Execute a command. - */ - - public void executeCommand(String command) { - //### Treatment of 'out' here is dirty... - out = env.getOutputSink(); - if (echo) { - out.println(">>> " + command); - } - StringTokenizer t = new StringTokenizer(command); - try { - String cmd; - if (t.hasMoreTokens()) { - cmd = t.nextToken().toLowerCase(); - lastCommand = cmd; - } else { - cmd = lastCommand; - } - if (cmd.equals("print")) { - commandPrint(t, false); - } else if (cmd.equals("eval")) { - commandPrint(t, false); - } else if (cmd.equals("dump")) { - commandPrint(t, true); - } else if (cmd.equals("locals")) { - commandLocals(); - } else if (cmd.equals("classes")) { - commandClasses(); - } else if (cmd.equals("methods")) { - commandMethods(t); - } else if (cmd.equals("threads")) { - commandThreads(t); - } else if (cmd.equals("thread")) { - commandThread(t); - } else if (cmd.equals("suspend")) { - commandSuspend(t); - } else if (cmd.equals("resume")) { - commandResume(t); - } else if (cmd.equals("cont")) { - commandCont(); - } else if (cmd.equals("threadgroups")) { - commandThreadGroups(); - } else if (cmd.equals("threadgroup")) { - commandThreadGroup(t); - } else if (cmd.equals("run")) { - commandRun(t); - } else if (cmd.equals("load")) { - commandLoad(t); - } else if (cmd.equals("connect")) { - commandConnect(t); - } else if (cmd.equals("attach")) { - commandAttach(t); - } else if (cmd.equals("detach")) { - commandDetach(t); - } else if (cmd.equals("interrupt")) { - commandInterrupt(t); -//### Not implemented. -// } else if (cmd.equals("catch")) { -// commandCatchException(t); -//### Not implemented. -// } else if (cmd.equals("ignore")) { -// commandIgnoreException(t); - } else if (cmd.equals("step")) { - commandStep(t); - } else if (cmd.equals("stepi")) { - commandStepi(); - } else if (cmd.equals("next")) { - commandNext(); - } else if (cmd.equals("nexti")) { - commandNexti(); - } else if (cmd.equals("kill")) { - commandKill(t); - } else if (cmd.equals("where")) { - commandWhere(t, false); - } else if (cmd.equals("wherei")) { - commandWhere(t, true); - } else if (cmd.equals("up")) { - commandUp(t); - } else if (cmd.equals("down")) { - commandDown(t); - } else if (cmd.equals("frame")) { - commandFrame(t); - } else if (cmd.equals("stop")) { - commandStop(t); - } else if (cmd.equals("clear")) { - commandClear(t); - } else if (cmd.equals("list")) { - commandList(t); - } else if (cmd.equals("use")) { - commandUse(t); - } else if (cmd.equals("sourcepath")) { - commandSourcepath(t); - } else if (cmd.equals("classpath")) { - commandClasspath(t); - } else if (cmd.equals("monitor")) { - commandMonitor(t); - } else if (cmd.equals("unmonitor")) { - commandUnmonitor(t); - } else if (cmd.equals("view")) { - commandView(t); -// } else if (cmd.equals("read")) { -// readCommand(t); - } else if (cmd.equals("help") || cmd.equals("?")) { - help(); - } else if (cmd.equals("quit") || cmd.equals("exit")) { - try { - runtime.detach(); - } catch (NoSessionException e) { - // ignore - } - env.terminate(); - } else { - //### Dubious repeat-count feature inherited from 'jdb' - if (t.hasMoreTokens()) { - try { - int repeat = Integer.parseInt(cmd); - String subcom = t.nextToken(""); - while (repeat-- > 0) { - executeCommand(subcom); - } - return; - } catch (NumberFormatException exc) { - } - } - out.println("huh? Try help..."); - out.flush(); - } - } catch (NoSessionException e) { - out.println("There is no currently attached VM session."); - out.flush(); - } catch (Exception e) { - out.println("Internal exception: " + e.toString()); - out.flush(); - System.out.println("JDB internal exception: " + e.toString()); - e.printStackTrace(); - } - out.show(); - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandTool.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandTool.java deleted file mode 100644 index d010ec2f56b..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CommandTool.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.io.*; -import java.util.*; - -import javax.swing.*; -import java.awt.BorderLayout; -import java.awt.event.*; - -import com.sun.jdi.*; -import com.sun.jdi.event.*; - -import com.sun.tools.example.debug.bdi.*; -import com.sun.tools.example.debug.event.*; - -public class CommandTool extends JPanel { - - private static final long serialVersionUID = 8613516856378346415L; - - private Environment env; - - private ContextManager context; - private ExecutionManager runtime; - private SourceManager sourceManager; - - private TypeScript script; - - private static final String DEFAULT_CMD_PROMPT = "Command:"; - - public CommandTool(Environment env) { - - super(new BorderLayout()); - - this.env = env; - this.context = env.getContextManager(); - this.runtime = env.getExecutionManager(); - this.sourceManager = env.getSourceManager(); - - script = new TypeScript(DEFAULT_CMD_PROMPT, false); //no echo - this.add(script); - - final CommandInterpreter interpreter = - new CommandInterpreter(env); - - // Establish handler for incoming commands. - - script.addActionListener(new ActionListener() { - @Override - public void actionPerformed(ActionEvent e) { - interpreter.executeCommand(script.readln()); - } - }); - - // Establish ourselves as the listener for VM diagnostics. - - OutputListener diagnosticsListener = - new TypeScriptOutputListener(script, true); - runtime.addDiagnosticsListener(diagnosticsListener); - - // Establish ourselves as the shared debugger typescript. - - env.setTypeScript(new PrintWriter(new TypeScriptWriter(script))); - - // Handle VM events. - - TTYDebugListener listener = new TTYDebugListener(diagnosticsListener); - - runtime.addJDIListener(listener); - runtime.addSessionListener(listener); - runtime.addSpecListener(listener); - context.addContextListener(listener); - - //### remove listeners on exit! - - } - - private class TTYDebugListener implements - JDIListener, SessionListener, SpecListener, ContextListener { - - private OutputListener diagnostics; - - TTYDebugListener(OutputListener diagnostics) { - this.diagnostics = diagnostics; - } - - // JDIListener - - @Override - public void accessWatchpoint(AccessWatchpointEventSet e) { - setThread(e); - for (EventIterator it = e.eventIterator(); it.hasNext(); ) { - it.nextEvent(); - diagnostics.putString("Watchpoint hit: " + - locationString(e)); - } - } - - @Override - public void classPrepare(ClassPrepareEventSet e) { - if (context.getVerboseFlag()) { - String name = e.getReferenceType().name(); - diagnostics.putString("Class " + name + " loaded"); - } - } - - @Override - public void classUnload(ClassUnloadEventSet e) { - if (context.getVerboseFlag()) { - diagnostics.putString("Class " + e.getClassName() + - " unloaded."); - } - } - - @Override - public void exception(ExceptionEventSet e) { - setThread(e); - String name = e.getException().referenceType().name(); - diagnostics.putString("Exception: " + name); - } - - @Override - public void locationTrigger(LocationTriggerEventSet e) { - String locString = locationString(e); - setThread(e); - for (EventIterator it = e.eventIterator(); it.hasNext(); ) { - Event evt = it.nextEvent(); - if (evt instanceof BreakpointEvent) { - diagnostics.putString("Breakpoint hit: " + locString); - } else if (evt instanceof StepEvent) { - diagnostics.putString("Step completed: " + locString); - } else if (evt instanceof MethodEntryEvent) { - diagnostics.putString("Method entered: " + locString); - } else if (evt instanceof MethodExitEvent) { - diagnostics.putString("Method exited: " + locString); - } else { - diagnostics.putString("UNKNOWN event: " + e); - } - } - } - - @Override - public void modificationWatchpoint(ModificationWatchpointEventSet e) { - setThread(e); - for (EventIterator it = e.eventIterator(); it.hasNext(); ) { - it.nextEvent(); - diagnostics.putString("Watchpoint hit: " + - locationString(e)); - } - } - - @Override - public void threadDeath(ThreadDeathEventSet e) { - if (context.getVerboseFlag()) { - diagnostics.putString("Thread " + e.getThread() + - " ended."); - } - } - - @Override - public void threadStart(ThreadStartEventSet e) { - if (context.getVerboseFlag()) { - diagnostics.putString("Thread " + e.getThread() + - " started."); - } - } - - @Override - public void vmDeath(VMDeathEventSet e) { - script.setPrompt(DEFAULT_CMD_PROMPT); - diagnostics.putString("VM exited"); - } - - @Override - public void vmDisconnect(VMDisconnectEventSet e) { - script.setPrompt(DEFAULT_CMD_PROMPT); - diagnostics.putString("Disconnected from VM"); - } - - @Override - public void vmStart(VMStartEventSet e) { - script.setPrompt(DEFAULT_CMD_PROMPT); - diagnostics.putString("VM started"); - } - - // SessionListener - - @Override - public void sessionStart(EventObject e) {} - - @Override - public void sessionInterrupt(EventObject e) { - Thread.yield(); // fetch output - diagnostics.putString("VM interrupted by user."); - script.setPrompt(DEFAULT_CMD_PROMPT); - } - - @Override - public void sessionContinue(EventObject e) { - diagnostics.putString("Execution resumed."); - script.setPrompt(DEFAULT_CMD_PROMPT); - } - - // SpecListener - - @Override - public void breakpointSet(SpecEvent e) { - EventRequestSpec spec = e.getEventRequestSpec(); - diagnostics.putString("Breakpoint set at " + spec + "."); - } - @Override - public void breakpointDeferred(SpecEvent e) { - EventRequestSpec spec = e.getEventRequestSpec(); - diagnostics.putString("Breakpoint will be set at " + - spec + " when its class is loaded."); - } - @Override - public void breakpointDeleted(SpecEvent e) { - EventRequestSpec spec = e.getEventRequestSpec(); - diagnostics.putString("Breakpoint at " + spec.toString() + " deleted."); - } - @Override - public void breakpointResolved(SpecEvent e) { - EventRequestSpec spec = e.getEventRequestSpec(); - diagnostics.putString("Breakpoint resolved to " + spec.toString() + "."); - } - @Override - public void breakpointError(SpecErrorEvent e) { - EventRequestSpec spec = e.getEventRequestSpec(); - diagnostics.putString("Deferred breakpoint at " + - spec + " could not be resolved:" + - e.getReason()); - } - -//### Add info for watchpoints and exceptions - - @Override - public void watchpointSet(SpecEvent e) { - } - @Override - public void watchpointDeferred(SpecEvent e) { - } - @Override - public void watchpointDeleted(SpecEvent e) { - } - @Override - public void watchpointResolved(SpecEvent e) { - } - @Override - public void watchpointError(SpecErrorEvent e) { - } - - @Override - public void exceptionInterceptSet(SpecEvent e) { - } - @Override - public void exceptionInterceptDeferred(SpecEvent e) { - } - @Override - public void exceptionInterceptDeleted(SpecEvent e) { - } - @Override - public void exceptionInterceptResolved(SpecEvent e) { - } - @Override - public void exceptionInterceptError(SpecErrorEvent e) { - } - - - // ContextListener. - - // If the user selects a new current thread or frame, update prompt. - - @Override - public void currentFrameChanged(CurrentFrameChangedEvent e) { - // Update prompt only if affect thread is current. - ThreadReference thread = e.getThread(); - if (thread == context.getCurrentThread()) { - script.setPrompt(promptString(thread, e.getIndex())); - } - } - - } - - private String locationString(LocatableEventSet e) { - Location loc = e.getLocation(); - return "thread=\"" + e.getThread().name() + - "\", " + Utils.locationString(loc); - } - - private void setThread(LocatableEventSet e) { - if (!e.suspendedNone()) { - Thread.yield(); // fetch output - script.setPrompt(promptString(e.getThread(), 0)); - //### Current thread should be set elsewhere, e.g., - //### in ContextManager - //### context.setCurrentThread(thread); - } - } - - private String promptString(ThreadReference thread, int frameIndex) { - if (thread == null) { - return DEFAULT_CMD_PROMPT; - } else { - // Frame indices are presented to user as indexed from 1. - return (thread.name() + "[" + (frameIndex + 1) + "]:"); - } - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ContextManager.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ContextManager.java deleted file mode 100644 index fb2416789e8..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/ContextManager.java +++ /dev/null @@ -1,362 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.io.*; -import java.util.*; - -import com.sun.jdi.*; -import com.sun.tools.example.debug.event.*; -import com.sun.tools.example.debug.bdi.*; - -public class ContextManager { - - private ClassManager classManager; - private ExecutionManager runtime; - - private String mainClassName; - private String vmArguments; - private String commandArguments; - private String remotePort; - - private ThreadReference currentThread; - - private boolean verbose; - - private ArrayList contextListeners = new ArrayList(); - - public ContextManager(Environment env) { - classManager = env.getClassManager(); - runtime = env.getExecutionManager(); - mainClassName = ""; - vmArguments = ""; - commandArguments = ""; - currentThread = null; - - ContextManagerListener listener = new ContextManagerListener(); - runtime.addJDIListener(listener); - runtime.addSessionListener(listener); - } - - // Program execution defaults. - - //### Should there be change listeners for these? - //### They would be needed if we expected a dialog to be - //### synchronized with command input while it was open. - - public String getMainClassName() { - return mainClassName; - } - - public void setMainClassName(String mainClassName) { - this.mainClassName = mainClassName; - } - - public String getVmArguments() { - return processClasspathDefaults(vmArguments); - } - - public void setVmArguments(String vmArguments) { - this.vmArguments = vmArguments; - } - - public String getProgramArguments() { - return commandArguments; - } - - public void setProgramArguments(String commandArguments) { - this.commandArguments = commandArguments; - } - - public String getRemotePort() { - return remotePort; - } - - public void setRemotePort(String remotePort) { - this.remotePort = remotePort; - - } - - - // Miscellaneous debugger session preferences. - - public boolean getVerboseFlag() { - return verbose; - } - - public void setVerboseFlag(boolean verbose) { - this.verbose = verbose; - } - - - // Thread focus. - - public ThreadReference getCurrentThread() { - return currentThread; - } - - public void setCurrentThread(ThreadReference t) { - if (t != currentThread) { - currentThread = t; - notifyCurrentThreadChanged(t); - } - } - - public void setCurrentThreadInvalidate(ThreadReference t) { - currentThread = t; - notifyCurrentFrameChanged(runtime.threadInfo(t), - 0, true); - } - - public void invalidateCurrentThread() { - notifyCurrentFrameChanged(null, 0, true); - } - - - // If a view is displaying the current thread, it may - // choose to indicate which frame is current in the - // sense of the command-line UI. It may also "warp" the - // selection to that frame when changed by an 'up' or 'down' - // command. Hence, a notifier is provided. - - /****** - public int getCurrentFrameIndex() { - return getCurrentFrameIndex(currentThreadInfo); - } - ******/ - - public int getCurrentFrameIndex(ThreadReference t) { - return getCurrentFrameIndex(runtime.threadInfo(t)); - } - - //### Used in StackTraceTool. - public int getCurrentFrameIndex(ThreadInfo tinfo) { - if (tinfo == null) { - return 0; - } - Integer currentFrame = (Integer)tinfo.getUserObject(); - if (currentFrame == null) { - return 0; - } else { - return currentFrame.intValue(); - } - } - - public int moveCurrentFrameIndex(ThreadReference t, int count) throws VMNotInterruptedException { - return setCurrentFrameIndex(t,count, true); - } - - public int setCurrentFrameIndex(ThreadReference t, int newIndex) throws VMNotInterruptedException { - return setCurrentFrameIndex(t, newIndex, false); - } - - public int setCurrentFrameIndex(int newIndex) throws VMNotInterruptedException { - if (currentThread == null) { - return 0; - } else { - return setCurrentFrameIndex(currentThread, newIndex, false); - } - } - - private int setCurrentFrameIndex(ThreadReference t, int x, boolean relative) throws VMNotInterruptedException { - boolean sameThread = t.equals(currentThread); - ThreadInfo tinfo = runtime.threadInfo(t); - if (tinfo == null) { - return 0; - } - int maxIndex = tinfo.getFrameCount()-1; - int oldIndex = getCurrentFrameIndex(tinfo); - int newIndex = relative? oldIndex + x : x; - if (newIndex > maxIndex) { - newIndex = maxIndex; - } else if (newIndex < 0) { - newIndex = 0; - } - if (!sameThread || newIndex != oldIndex) { // don't recurse - setCurrentFrameIndex(tinfo, newIndex); - } - return newIndex - oldIndex; - } - - private void setCurrentFrameIndex(ThreadInfo tinfo, int index) { - tinfo.setUserObject(index); - //### In fact, the value may not have changed at this point. - //### We need to signal that the user attempted to change it, - //### however, so that the selection can be "warped" to the - //### current location. - notifyCurrentFrameChanged(tinfo.thread(), index); - } - - public StackFrame getCurrentFrame() throws VMNotInterruptedException { - return getCurrentFrame(runtime.threadInfo(currentThread)); - } - - public StackFrame getCurrentFrame(ThreadReference t) throws VMNotInterruptedException { - return getCurrentFrame(runtime.threadInfo(t)); - } - - public StackFrame getCurrentFrame(ThreadInfo tinfo) throws VMNotInterruptedException { - int index = getCurrentFrameIndex(tinfo); - try { - // It is possible, though unlikely, that the VM was interrupted - // before the thread created its Java stack. - return tinfo.getFrame(index); - } catch (FrameIndexOutOfBoundsException e) { - return null; - } - } - - public void addContextListener(ContextListener cl) { - contextListeners.add(cl); - } - - public void removeContextListener(ContextListener cl) { - contextListeners.remove(cl); - } - - //### These notifiers are fired only in response to USER-INITIATED changes - //### to the current thread and current frame. When the current thread is set automatically - //### after a breakpoint hit or step completion, no event is generated. Instead, - //### interested parties are expected to listen for the BreakpointHit and StepCompleted - //### events. This convention is unclean, and I believe that it reflects a defect in - //### in the current architecture. Unfortunately, however, we cannot guarantee the - //### order in which various listeners receive a given event, and the handlers for - //### the very same events that cause automatic changes to the current thread may also - //### need to know the current thread. - - private void notifyCurrentThreadChanged(ThreadReference t) { - ThreadInfo tinfo = null; - int index = 0; - if (t != null) { - tinfo = runtime.threadInfo(t); - index = getCurrentFrameIndex(tinfo); - } - notifyCurrentFrameChanged(tinfo, index, false); - } - - private void notifyCurrentFrameChanged(ThreadReference t, int index) { - notifyCurrentFrameChanged(runtime.threadInfo(t), - index, false); - } - - private void notifyCurrentFrameChanged(ThreadInfo tinfo, int index, - boolean invalidate) { - ArrayList l = new ArrayList(contextListeners); - CurrentFrameChangedEvent evt = - new CurrentFrameChangedEvent(this, tinfo, index, invalidate); - for (int i = 0; i < l.size(); i++) { - l.get(i).currentFrameChanged(evt); - } - } - - private class ContextManagerListener extends JDIAdapter - implements SessionListener, JDIListener { - - // SessionListener - - @Override - public void sessionStart(EventObject e) { - invalidateCurrentThread(); - } - - @Override - public void sessionInterrupt(EventObject e) { - setCurrentThreadInvalidate(currentThread); - } - - @Override - public void sessionContinue(EventObject e) { - invalidateCurrentThread(); - } - - // JDIListener - - @Override - public void locationTrigger(LocationTriggerEventSet e) { - setCurrentThreadInvalidate(e.getThread()); - } - - @Override - public void exception(ExceptionEventSet e) { - setCurrentThreadInvalidate(e.getThread()); - } - - @Override - public void vmDisconnect(VMDisconnectEventSet e) { - invalidateCurrentThread(); - } - - } - - - /** - * Add a -classpath argument to the arguments passed to the exec'ed - * VM with the contents of CLASSPATH environment variable, - * if -classpath was not already specified. - * - * @param javaArgs the arguments to the VM being exec'd that - * potentially has a user specified -classpath argument. - * @return a javaArgs whose -classpath option has been added - */ - - private String processClasspathDefaults(String javaArgs) { - if (javaArgs.indexOf("-classpath ") == -1) { - StringBuilder munged = new StringBuilder(javaArgs); - SearchPath classpath = classManager.getClassPath(); - if (classpath.isEmpty()) { - String envcp = System.getProperty("env.class.path"); - if ((envcp != null) && (envcp.length() > 0)) { - munged.append(" -classpath " + envcp); - } - } else { - munged.append(" -classpath " + classpath.asString()); - } - return munged.toString(); - } else { - return javaArgs; - } - } - - private String appendPath(String path1, String path2) { - if (path1 == null || path1.length() == 0) { - return path2 == null ? "." : path2; - } else if (path2 == null || path2.length() == 0) { - return path1; - } else { - return path1 + File.pathSeparator + path2; - } - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CurrentFrameChangedEvent.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CurrentFrameChangedEvent.java deleted file mode 100644 index b933e758f38..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/CurrentFrameChangedEvent.java +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import com.sun.jdi.*; -import com.sun.tools.example.debug.bdi.*; -import java.util.EventObject; - -public class CurrentFrameChangedEvent extends EventObject { - - private static final long serialVersionUID = 4214479486546762179L; - private ThreadInfo tinfo; - private int index; - private boolean invalidate; - - public CurrentFrameChangedEvent(Object source, ThreadInfo tinfo, - int index, boolean invalidate) { - super(source); - this.tinfo = tinfo; - this.index = index; - this.invalidate = invalidate; - } - - public ThreadReference getThread() { - return tinfo == null? null : tinfo.thread(); - } - - public ThreadInfo getThreadInfo() { - return tinfo; - } - - public int getIndex() { - return index; - } - - public boolean getInvalidate() { - return invalidate; - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/Environment.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/Environment.java deleted file mode 100644 index b06ae4d6c79..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/Environment.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.io.*; -import com.sun.jdi.*; -import com.sun.tools.example.debug.bdi.*; - -public class Environment { - - private SourceManager sourceManager; - private ClassManager classManager; - private ContextManager contextManager; - private MonitorListModel monitorListModel; - private ExecutionManager runtime; - - private PrintWriter typeScript; - - private boolean verbose; - - public Environment() { - this.classManager = new ClassManager(this); - //### Order of the next three lines is important! (FIX THIS) - this.runtime = new ExecutionManager(); - this.sourceManager = new SourceManager(this); - this.contextManager = new ContextManager(this); - this.monitorListModel = new MonitorListModel(this); - } - - // Services used by debugging tools. - - public SourceManager getSourceManager() { - return sourceManager; - } - - public ClassManager getClassManager() { - return classManager; - } - - public ContextManager getContextManager() { - return contextManager; - } - - public MonitorListModel getMonitorListModel() { - return monitorListModel; - } - - public ExecutionManager getExecutionManager() { - return runtime; - } - - //### TODO: - //### Tools should attach/detach from environment - //### via a property, which should call an 'addTool' - //### method when set to maintain a registry of - //### tools for exit-time cleanup, etc. Tool - //### class constructors should be argument-free, so - //### that they may be instantiated by bean builders. - //### Will also need 'removeTool' in case property - //### value is changed. - // - // public void addTool(Tool t); - // public void removeTool(Tool t); - - public void terminate() { - System.exit(0); - } - - // public void refresh(); // notify all tools to refresh their views - - - // public void addStatusListener(StatusListener l); - // public void removeStatusListener(StatusListener l); - - // public void addOutputListener(OutputListener l); - // public void removeOutputListener(OutputListener l); - - public void setTypeScript(PrintWriter writer) { - typeScript = writer; - } - - public void error(String message) { - if (typeScript != null) { - typeScript.println(message); - } else { - System.out.println(message); - } - } - - public void failure(String message) { - if (typeScript != null) { - typeScript.println(message); - } else { - System.out.println(message); - } - } - - public void notice(String message) { - if (typeScript != null) { - typeScript.println(message); - } else { - System.out.println(message); - } - } - - public OutputSink getOutputSink() { - return new OutputSink(typeScript); - } - - public void viewSource(String fileName) { - //### HACK ### - //### Should use listener here. - com.sun.tools.example.debug.gui.GUI.srcTool.showSourceFile(fileName); - } - - public void viewLocation(Location locn) { - //### HACK ### - //### Should use listener here. - //### Should we use sourceForLocation here? - com.sun.tools.example.debug.gui.GUI.srcTool.showSourceForLocation(locn); - } - - //### Also in 'ContextManager'. Do we need both? - - public boolean getVerboseFlag() { - return verbose; - } - - public void setVerboseFlag(boolean verbose) { - this.verbose = verbose; - } - -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/GUI.java b/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/GUI.java deleted file mode 100644 index eefbcfa7b61..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/gui/GUI.java +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.debug.gui; - -import java.io.*; -import javax.swing.*; -import javax.swing.border.*; -import java.awt.*; -import java.awt.event.*; - -import com.sun.jdi.*; -import com.sun.tools.example.debug.bdi.*; - -public class GUI extends JPanel { - - private static final long serialVersionUID = 3292463234530679091L; - private CommandTool cmdTool; - private ApplicationTool appTool; - //###HACK## - //### There is currently dirty code in Environment that - //### accesses this directly. - //private SourceTool srcTool; - public static SourceTool srcTool; - - private SourceTreeTool sourceTreeTool; - private ClassTreeTool classTreeTool; - private ThreadTreeTool threadTreeTool; - private StackTraceTool stackTool; - private MonitorTool monitorTool; - - public static final String progname = "javadt"; - public static final String version = "1.0Beta"; //### FIX ME. - public static final String windowBanner = "Java(tm) platform Debug Tool"; - - private Font fixedFont = new Font("monospaced", Font.PLAIN, 10); - - private GUI(Environment env) { - setLayout(new BorderLayout()); - - setBorder(new EmptyBorder(5, 5, 5, 5)); - - add(new JDBToolBar(env), BorderLayout.NORTH); - - srcTool = new SourceTool(env); - srcTool.setPreferredSize(new java.awt.Dimension(500, 300)); - srcTool.setTextFont(fixedFont); - - stackTool = new StackTraceTool(env); - stackTool.setPreferredSize(new java.awt.Dimension(500, 100)); - - monitorTool = new MonitorTool(env); - monitorTool.setPreferredSize(new java.awt.Dimension(500, 50)); - - JSplitPane right = new JSplitPane(JSplitPane.VERTICAL_SPLIT, srcTool, - new JSplitPane(JSplitPane.VERTICAL_SPLIT, stackTool, monitorTool)); - - sourceTreeTool = new SourceTreeTool(env); - sourceTreeTool.setPreferredSize(new java.awt.Dimension(200, 450)); - - classTreeTool = new ClassTreeTool(env); - classTreeTool.setPreferredSize(new java.awt.Dimension(200, 450)); - - threadTreeTool = new ThreadTreeTool(env); - threadTreeTool.setPreferredSize(new java.awt.Dimension(200, 450)); - - JTabbedPane treePane = new JTabbedPane(SwingConstants.BOTTOM); - treePane.addTab("Source", null, sourceTreeTool); - treePane.addTab("Classes", null, classTreeTool); - treePane.addTab("Threads", null, threadTreeTool); - - JSplitPane centerTop = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, treePane, right); - - cmdTool = new CommandTool(env); - cmdTool.setPreferredSize(new java.awt.Dimension(700, 150)); - - appTool = new ApplicationTool(env); - appTool.setPreferredSize(new java.awt.Dimension(700, 200)); - - JSplitPane centerBottom = new JSplitPane(JSplitPane.VERTICAL_SPLIT, cmdTool, appTool); - // centerBottom.setPreferredSize(new java.awt.Dimension(700, 350)); - - JSplitPane center = new JSplitPane(JSplitPane.VERTICAL_SPLIT, centerTop, centerBottom); - - add(center, BorderLayout.CENTER); - - - } - - private static void usage() { - String separator = File.pathSeparator; - System.out.println("Usage: " + progname + " "); - System.out.println(); - System.out.println("where options include:"); - System.out.println(" -help print out this message and exit"); - System.out.println(" -sourcepath "); - System.out.println(" list directories in which to look for source files"); - System.out.println(" -remote :"); - System.out.println(" host machine and port number of interpreter to attach to"); - System.out.println(" -dbgtrace [flags] print info for debugging " + progname); - System.out.println(); - System.out.println("options forwarded to debuggee process:"); - System.out.println(" -v -verbose[:class|gc|jni]"); - System.out.println(" turn on verbose mode"); - System.out.println(" -D= set a system property"); - System.out.println(" -classpath "); - System.out.println(" list directories in which to look for classes"); - System.out.println(" -X

Example JDI Applications

-This example download contains the source code and -documentation for three applications written using -the JavaTM Debug Interface (JDI) -of the Java Platform Debugger Architecture (JPDA). -They are provided as educational tools and as starting -points for debugger development. -

-In increasing order of complexity: -

    -
  • Trace displays traces -of program execution. It is very simple (less than 600 lines) -yet uses most of the basic JDI functionality. It is a -good starting point. -
  • Jdb is the command line debugger -distributed with the J2SE SDK. -
  • Javadt is the beginnings of -a GUI debugger. -
-

-Trace is in the trace directory. -Jdb and Javadt share a package, and are under the -debug directory. - -

Required Set-up

- -

Where is JPDA?

-New versions of the J2SE SDK have JPDA included. For -older versions JPDA must be separately downloaded. -
-
SDKs with JPDA included -
J2SE SDK v1.3 and later and J2SE SDK for Linux v1.2.2 -
SDKs requiring JPDA download -
J2SE SDK v1.2.1 and v1.2.2 for Solaris and Windows -
Other SDKs -
Check with vendor -
-

-

Set-up for J2SE SDKs with JPDA included

-Your classpath must include the JDI Library code, which is -in tools.jar in the lib directory. -This is needed for both compiling the example code and -executing it. -

-

Set-up for J2SE SDKs without JPDA - Solaris

-Download JPDA v1.0 from -http://java.sun.com/products/jpda. Follow the -Installation Instructions -found there. Pay particular attention to setting the library -path. -

-Your classpath must include the JDI Library code, which is -in jpda_home/lib/tools.jar. -This is needed for both compiling the example code and -executing it. -

-

Set-up for J2SE SDKs without JPDA - Windows

-Download JPDA v1.0 from -http://java.sun.com/products/jpda. Follow the -Installation Instructions -found there. Be sure to add: -
-        jpda_home\bin
-
-to your path. -

-Your classpath must include the JDI Library code, which is -in jpda_home\lib\tools.jar. -This is needed for both compiling the example code and -executing it. -

-


-
java-debugger@java.sun.com
-

-

-

- - - diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/javadt.html b/jdk/src/demo/share/jpda/com/sun/tools/example/doc/javadt.html deleted file mode 100644 index f9d28a166bb..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/javadt.html +++ /dev/null @@ -1,174 +0,0 @@ - - - Release notes for the javadt debugger - - -

Release notes for the javadt debugger

- -

-As a demonstration of the - -JavaTM Platform Debugger Architecture -we are providing source code for -a simple GUI debugging tool - javadt. -It is included as an example and demonstration of - -JDI. It is not a finished or polished debugger and is -missing many features of importance for real debugging work. -

- -

Invoking javadt

-

-javadt can be run by executing: -

-   java com.sun.tools.example.debug.gui.GUI <options>.. <class-name>
-
-where <class-name> is the name you would normally -place on the java command line. -Note: the path to the JDI Library and to -the compiled javadt class files must be on the class path -used to invoke gui.GUI. -

-For example, you can invoke the javadt debugger as follows: -

-   java com.sun.tools.example.debug.gui.GUI -classpath . Hello
-
-Note: this -classpath option controls the -class path for the Hello application. -Once the window appears, you can issue the 'run' command to begin -execution immediately. It is also -possible to give the class name in the 'run' command, in -which case it may be omitted when invoking the debugger from the -shell. -

-The classpath may also be set from within the debugger, using the -'classpath' command. Currently, other arguments to the VM must be -given on the shell command line when the debugger is initially -invoked. The most recently mentioned classpath, VM arguments, main -class name, and program arguments are retained as defaults for later -'run' and 'load' commands. (Unfortunately, at present, the debugger -will likely crash if you attempt to begin another debugging session -with another debuggee process from within the same invocation of the -debugger. You should exit to the shell and start a new debugger -process.) -

- -

Using javadt

-The javadt normally displays context related to the "current thread", -that is, the thread that most recently encountered a breakpoint, threw -an uncaught exception, or was single-stepped by the user. When -program execution is suspended on account of one of these events, a -current thread exists, and the javadt displays the following information -about it: -

-

    -
  • A stack backtrace. - -
  • The source code surrounding the line corresponding to the - instruction counter for the thread, if the source code is - available. -
-

-In addition, a tabbed pane allows the user to view one of three -additional views: -

-

    -
  • A tree of all source files available on the source path. - -
  • A tree of all loaded class files, organized hierarchically - by package. - -
  • A tree of all active threads, organized hierarchically - by thread group. -
-

-By clicking on the name of a source file, the source view can be -directed to display it. Likewise, clicking on a thread will make that -thread the current thread. These features are normally used while the -program is suspended, e.g, at a breakpoint. Upon resumption and -encountering another breakpoint, for example, the current thread will -be automatically reset and the views will be updated. The views tile -the javadt display, and are adjustable in size. -

-The javadt functionality is rather basic, thus a command-line interaction -window is also provided that allows access to functions that are not -yet exposed in the javadt. In particular, it is necessary to use the -command line in order to set breakpoints and examine variables. The -javadt debugger command interpreter implements roughly a subset of the -jdb - functionality, but adds a few commands of its own. The -'help' command lists the complete set of commands and their function. -Shortcuts for a set of the most common commands is provided on a -button-bar at the top of the display. -

-The program to be debugged may be started either as a child of the -debugger, or the debugger can be attached to an existing process, -provided that its VM is prepared to accept the connection. If the -debuggee is started by the debugger as a child, a line-oriented -interface to its standard input, output, and error streams is provided -in an application interaction pane. -

-The debugger expects to find the program source code on its -sourcepath, set with the 'use' or 'sourcepath' command. If you find -that sources are not being displayed because the sourcepath is -incorrect, you may change it at that time, and the source view will be -immediately updated. -

-The message "No current thread" is often encountered when stepping -through a program. This message does not mean that the thread or -the VM has died, merely that a current thread is undefined. This -situation can easily occur unexpectedly when the program being -stepped is waiting, eg., for input. The VM appears to be stopped, -as it would be after the successful completion of a step, but it -is considered to be "running", not "interrupted". The prompt -in the command interaction pane indicates the state by changing -to a thread name and frame number when the VM is interrupted. -When it is running, the prompt "Command:" is displayed. -

-

Source for javadt

-Full source code for javadt is included under the -debug directory of examples.jar. -Note: these directories also include the -source for jdb. -Source code for these example applications is included to provide concrete -examples for debugger developers. Example code may be used, modified -and redistributed by debugger developers providing they adhere to the -terms in the COPYRIGHT notice. -

-javadt uses the following packages (found under the -debug directory): -

-
gui -
User interface code -
bdi -
Debugger core code -
events -
Event Set code -
expr -
Expression processing code -
-

-

Building javadt

-To build the javadt classes from the -provided source files under the debug directory, -you need only to compile them. No special -options are required, aside from those which set your classpath to -include the JDI Library. -

-

-However, if you want to modify the expression parser in the file -Expr.jj, you will need the - -JavaCC parser generator. -It is available free from -Metamata -(now part of WebGain). -

-


-
java-debugger@java.sun.com
-

-

-

- - diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/jdb.html b/jdk/src/demo/share/jpda/com/sun/tools/example/doc/jdb.html deleted file mode 100644 index a8232b0207d..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/jdb.html +++ /dev/null @@ -1,104 +0,0 @@ - - - Release notes for the jdb debugger - - -  - - - - - -
-
-

Release notes for the jdb debugger

-
- -

-Home Page - -

-As a demonstration of the - -JavaTM Platform Debugger Architecture -we are providing source code for the jdb debugger, which was -re-written to use - -JDI. - -

-

jdb man pages

-
-jdb man pages for Windows -

-jdb man pages for Solaris -

-

-

Invoking jdb

-The jdb sample can be started by executing: -
-   java com.sun.tools.example.debug.tty.TTY <options>.. <class-name>
-
-where <class-name> is the name you would normally -place on the java command line. The -help -option provides information on options. -

-

-Note: the path to the JDI Library and to -the compiled jdb class files must be on the class path -used to invoke com.sun.tools.example.debug.tty.TTY. - -

-For more information on invoking and connecting, refer to the - -Connection and Invocation Details section of the - -JPDA documentation, -particularly the section on jdb. -

- - -

Source for jdb

-Full source code for jdb is included under the -debug directory of examples.jar. -Note: these directories also include the -source for javadt. -Source code for these example applications is included to provide concrete -examples for debugger developers. Example code may be used, modified -and redistributed by debugger developers providing they adhere to the -terms in the COPYRIGHT notice. -

-jdb uses the following packages (found under the -debug directory): -

-
tty -
Application code -
expr -
Expression processing code -
- -

-

Building jdb

-To completely rebuild the jdb classes from the -provided source files under the debug directory, -you need only to compile them. No special -options are required, aside from those which set your classpath to -include the JDI Library. -

-

-However, if you want to modify the expression parser in the file -Expr.jj, you will need the - -JavaCC parser generator. -It is available free from -Metamata -(now part of WebGain). -

-


-
java-debugger@java.sun.com
-

-

-

- - diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/trace.html b/jdk/src/demo/share/jpda/com/sun/tools/example/doc/trace.html deleted file mode 100644 index 8cae84dfe1e..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/doc/trace.html +++ /dev/null @@ -1,71 +0,0 @@ - - - - trace example - - -

trace example

- -Trace runs the Java language program passed as an argument and -generates a trace of its execution. Trace is a simple command -line tool that uses the - -Java Debug Interface (JDI). Programs need -not be compiled for debugging since this information is not -used. -

-Trace can be invoked as follows: -

-        java com.sun.tools.example.trace.Trace options class args
-
-Your classpath must include the JDI Library -(see set-up), -the path to the compiled trace class files, -and the path for the application being traced. -

-Available options are: - -

-  -output filename   
-        Set destination for output trace. By default output
-        goes to the terminal.
-
-  -all                 
-        Include system classes in output.  By default
-        java.*, javax.*, sun.* and com.sun.* events are
-        not diplayed.
-
-  -fields
-        Also show assignments into fields.
-
-  -help              
-        Print a help message
-
-
-class is the program to trace. args are the arguments to class. -

- -

Source for trace

-Full source code for trace is included in the -trace directory of examples.jar. -Source code for these example applications is included to provide concrete -examples for debugger developers. Example code may be used, modified -and redistributed by debugger developers providing they adhere to the -terms in the COPYRIGHT notice. - -

-

Building trace

-To completely rebuild the trace classes from the -provided source files in the trace directory, -you need only to compile them. No special -options are required, aside from those which set your classpath to -include the JDI Library. - -

-


-
java-debugger@java.sun.com
-

-

-

- - diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/trace/EventThread.java b/jdk/src/demo/share/jpda/com/sun/tools/example/trace/EventThread.java deleted file mode 100644 index 11084df5dd2..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/trace/EventThread.java +++ /dev/null @@ -1,353 +0,0 @@ -/* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.trace; - -import com.sun.jdi.*; -import com.sun.jdi.request.*; -import com.sun.jdi.event.*; - -import java.util.*; -import java.io.PrintWriter; - -/** - * This class processes incoming JDI events and displays them - * - * @author Robert Field - */ -public class EventThread extends Thread { - - private final VirtualMachine vm; // Running VM - private final String[] excludes; // Packages to exclude - private final PrintWriter writer; // Where output goes - - static String nextBaseIndent = ""; // Starting indent for next thread - - private boolean connected = true; // Connected to VM - private boolean vmDied = true; // VMDeath occurred - - // Maps ThreadReference to ThreadTrace instances - private Map traceMap = - new HashMap<>(); - - EventThread(VirtualMachine vm, String[] excludes, PrintWriter writer) { - super("event-handler"); - this.vm = vm; - this.excludes = excludes; - this.writer = writer; - } - - /** - * Run the event handling thread. - * As long as we are connected, get event sets off - * the queue and dispatch the events within them. - */ - @Override - public void run() { - EventQueue queue = vm.eventQueue(); - while (connected) { - try { - EventSet eventSet = queue.remove(); - EventIterator it = eventSet.eventIterator(); - while (it.hasNext()) { - handleEvent(it.nextEvent()); - } - eventSet.resume(); - } catch (InterruptedException exc) { - // Ignore - } catch (VMDisconnectedException discExc) { - handleDisconnectedException(); - break; - } - } - } - - /** - * Create the desired event requests, and enable - * them so that we will get events. - * @param excludes Class patterns for which we don't want events - * @param watchFields Do we want to watch assignments to fields - */ - void setEventRequests(boolean watchFields) { - EventRequestManager mgr = vm.eventRequestManager(); - - // want all exceptions - ExceptionRequest excReq = mgr.createExceptionRequest(null, - true, true); - // suspend so we can step - excReq.setSuspendPolicy(EventRequest.SUSPEND_ALL); - excReq.enable(); - - MethodEntryRequest menr = mgr.createMethodEntryRequest(); - for (int i=0; i 0) { - indent.append("| "); - } - - EventRequestManager mgr = vm.eventRequestManager(); - mgr.deleteEventRequest(event.request()); - } - - void threadDeathEvent(ThreadDeathEvent event) { - indent = new StringBuffer(baseIndent); - println("====== " + thread.name() + " end ======"); - } - } - - /** - * Returns the ThreadTrace instance for the specified thread, - * creating one if needed. - */ - ThreadTrace threadTrace(ThreadReference thread) { - ThreadTrace trace = traceMap.get(thread); - if (trace == null) { - trace = new ThreadTrace(thread); - traceMap.put(thread, trace); - } - return trace; - } - - /** - * Dispatch incoming events - */ - private void handleEvent(Event event) { - if (event instanceof ExceptionEvent) { - exceptionEvent((ExceptionEvent)event); - } else if (event instanceof ModificationWatchpointEvent) { - fieldWatchEvent((ModificationWatchpointEvent)event); - } else if (event instanceof MethodEntryEvent) { - methodEntryEvent((MethodEntryEvent)event); - } else if (event instanceof MethodExitEvent) { - methodExitEvent((MethodExitEvent)event); - } else if (event instanceof StepEvent) { - stepEvent((StepEvent)event); - } else if (event instanceof ThreadDeathEvent) { - threadDeathEvent((ThreadDeathEvent)event); - } else if (event instanceof ClassPrepareEvent) { - classPrepareEvent((ClassPrepareEvent)event); - } else if (event instanceof VMStartEvent) { - vmStartEvent((VMStartEvent)event); - } else if (event instanceof VMDeathEvent) { - vmDeathEvent((VMDeathEvent)event); - } else if (event instanceof VMDisconnectEvent) { - vmDisconnectEvent((VMDisconnectEvent)event); - } else { - throw new Error("Unexpected event type"); - } - } - - /*** - * A VMDisconnectedException has happened while dealing with - * another event. We need to flush the event queue, dealing only - * with exit events (VMDeath, VMDisconnect) so that we terminate - * correctly. - */ - synchronized void handleDisconnectedException() { - EventQueue queue = vm.eventQueue(); - while (connected) { - try { - EventSet eventSet = queue.remove(); - EventIterator iter = eventSet.eventIterator(); - while (iter.hasNext()) { - Event event = iter.nextEvent(); - if (event instanceof VMDeathEvent) { - vmDeathEvent((VMDeathEvent)event); - } else if (event instanceof VMDisconnectEvent) { - vmDisconnectEvent((VMDisconnectEvent)event); - } - } - eventSet.resume(); // Resume the VM - } catch (InterruptedException exc) { - // ignore - } - } - } - - private void vmStartEvent(VMStartEvent event) { - writer.println("-- VM Started --"); - } - - // Forward event for thread specific processing - private void methodEntryEvent(MethodEntryEvent event) { - threadTrace(event.thread()).methodEntryEvent(event); - } - - // Forward event for thread specific processing - private void methodExitEvent(MethodExitEvent event) { - threadTrace(event.thread()).methodExitEvent(event); - } - - // Forward event for thread specific processing - private void stepEvent(StepEvent event) { - threadTrace(event.thread()).stepEvent(event); - } - - // Forward event for thread specific processing - private void fieldWatchEvent(ModificationWatchpointEvent event) { - threadTrace(event.thread()).fieldWatchEvent(event); - } - - void threadDeathEvent(ThreadDeathEvent event) { - ThreadTrace trace = traceMap.get(event.thread()); - if (trace != null) { // only want threads we care about - trace.threadDeathEvent(event); // Forward event - } - } - - /** - * A new class has been loaded. - * Set watchpoints on each of its fields - */ - private void classPrepareEvent(ClassPrepareEvent event) { - EventRequestManager mgr = vm.eventRequestManager(); - List fields = event.referenceType().visibleFields(); - for (Field field : fields) { - ModificationWatchpointRequest req = - mgr.createModificationWatchpointRequest(field); - for (int i=0; i= 0) { - out.write(cbuf, 0, count); - } - out.flush(); - } catch(IOException exc) { - System.err.println("Child I/O Transfer - " + exc); - } - } -} diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/trace/Trace.java b/jdk/src/demo/share/jpda/com/sun/tools/example/trace/Trace.java deleted file mode 100644 index 2ce99f97a01..00000000000 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/trace/Trace.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2001, 2011, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute 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. - */ - -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. - */ - - -package com.sun.tools.example.trace; - -import com.sun.jdi.VirtualMachine; -import com.sun.jdi.Bootstrap; -import com.sun.jdi.connect.*; - -import java.util.Map; -import java.util.List; - -import java.io.PrintWriter; -import java.io.FileWriter; -import java.io.IOException; - -/** - * This program traces the execution of another program. - * See "java Trace -help". - * It is a simple example of the use of the Java Debug Interface. - * - * @author Robert Field - */ -public class Trace { - - // Running remote VM - private final VirtualMachine vm; - - // Thread transferring remote error stream to our error stream - private Thread errThread = null; - - // Thread transferring remote output stream to our output stream - private Thread outThread = null; - - // Mode for tracing the Trace program (default= 0 off) - private int debugTraceMode = 0; - - // Do we want to watch assignments to fields - private boolean watchFields = false; - - // Class patterns for which we don't want events - private String[] excludes = {"java.*", "javax.*", "sun.*", - "com.sun.*"}; - - /** - * main - */ - public static void main(String[] args) { - new Trace(args); - } - - /** - * Parse the command line arguments. - * Launch target VM. - * Generate the trace. - */ - Trace(String[] args) { - PrintWriter writer = new PrintWriter(System.out); - int inx; - for (inx = 0; inx < args.length; ++inx) { - String arg = args[inx]; - if (arg.charAt(0) != '-') { - break; - } - if (arg.equals("-output")) { - try { - writer = new PrintWriter(new FileWriter(args[++inx])); - } catch (IOException exc) { - System.err.println("Cannot open output file: " + args[inx] - + " - " + exc); - System.exit(1); - } - } else if (arg.equals("-all")) { - excludes = new String[0]; - } else if (arg.equals("-fields")) { - watchFields = true; - } else if (arg.equals("-dbgtrace")) { - debugTraceMode = Integer.parseInt(args[++inx]); - } else if (arg.equals("-help")) { - usage(); - System.exit(0); - } else { - System.err.println("No option: " + arg); - usage(); - System.exit(1); - } - } - if (inx >= args.length) { - System.err.println(" missing"); - usage(); - System.exit(1); - } - StringBuilder sb = new StringBuilder(); - sb.append(args[inx]); - for (++inx; inx < args.length; ++inx) { - sb.append(' '); - sb.append(args[inx]); - } - vm = launchTarget(sb.toString()); - generateTrace(writer); - } - - - /** - * Generate the trace. - * Enable events, start thread to display events, - * start threads to forward remote error and output streams, - * resume the remote VM, wait for the final event, and shutdown. - */ - void generateTrace(PrintWriter writer) { - vm.setDebugTraceMode(debugTraceMode); - EventThread eventThread = new EventThread(vm, excludes, writer); - eventThread.setEventRequests(watchFields); - eventThread.start(); - redirectOutput(); - vm.resume(); - - // Shutdown begins when event thread terminates - try { - eventThread.join(); - errThread.join(); // Make sure output is forwarded - outThread.join(); // before we exit - } catch (InterruptedException exc) { - // we don't interrupt - } - writer.close(); - } - - /** - * Launch target VM. - * Forward target's output and error. - */ - VirtualMachine launchTarget(String mainArgs) { - LaunchingConnector connector = findLaunchingConnector(); - Map arguments = - connectorArguments(connector, mainArgs); - try { - return connector.launch(arguments); - } catch (IOException exc) { - throw new Error("Unable to launch target VM: " + exc); - } catch (IllegalConnectorArgumentsException exc) { - throw new Error("Internal error: " + exc); - } catch (VMStartException exc) { - throw new Error("Target VM failed to initialize: " + - exc.getMessage()); - } - } - - void redirectOutput() { - Process process = vm.process(); - - // Copy target's output and error to our output and error. - errThread = new StreamRedirectThread("error reader", - process.getErrorStream(), - System.err); - outThread = new StreamRedirectThread("output reader", - process.getInputStream(), - System.out); - errThread.start(); - outThread.start(); - } - - /** - * Find a com.sun.jdi.CommandLineLaunch connector - */ - LaunchingConnector findLaunchingConnector() { - List connectors = Bootstrap.virtualMachineManager().allConnectors(); - for (Connector connector : connectors) { - if (connector.name().equals("com.sun.jdi.CommandLineLaunch")) { - return (LaunchingConnector)connector; - } - } - throw new Error("No launching connector"); - } - - /** - * Return the launching connector's arguments. - */ - Map connectorArguments(LaunchingConnector connector, String mainArgs) { - Map arguments = connector.defaultArguments(); - Connector.Argument mainArg = - (Connector.Argument)arguments.get("main"); - if (mainArg == null) { - throw new Error("Bad launching connector"); - } - mainArg.setValue(mainArgs); - - if (watchFields) { - // We need a VM that supports watchpoints - Connector.Argument optionArg = - (Connector.Argument)arguments.get("options"); - if (optionArg == null) { - throw new Error("Bad launching connector"); - } - optionArg.setValue("-classic"); - } - return arguments; - } - - /** - * Print command line usage help - */ - void usage() { - System.err.println("Usage: java Trace "); - System.err.println(" are:"); - System.err.println( -" -output Output trace to "); - System.err.println( -" -all Include system classes in output"); - System.err.println( -" -help Print this help message"); - System.err.println(" is the program to trace"); - System.err.println(" are the arguments to "); - } -} diff --git a/jdk/src/demo/share/jvmti/hprof/sample.makefile.txt b/jdk/src/demo/share/jvmti/hprof/sample.makefile.txt deleted file mode 100644 index e8f84dc8577..00000000000 --- a/jdk/src/demo/share/jvmti/hprof/sample.makefile.txt +++ /dev/null @@ -1,205 +0,0 @@ -# -# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions -# are met: -# -# - Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# -# - Redistributions in binary form must reproduce the above copyright -# notice, this list of conditions and the following disclaimer in the -# documentation and/or other materials provided with the distribution. -# -# - Neither the name of Oracle nor the names of its -# contributors may be used to endorse or promote products derived -# from this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS -# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, -# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR -# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, -# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR -# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF -# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING -# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# - -######################################################################## -# -# Sample GNU Makefile for building -# -# Example uses: -# gnumake JDK= OSNAME=solaris [OPT=true] [LIBARCH=sparc] -# gnumake JDK= OSNAME=solaris [OPT=true] [LIBARCH=sparcv9] -# gnumake JDK= OSNAME=linux [OPT=true] -# gnumake JDK= OSNAME=win32 [OPT=true] -# -######################################################################## - -# Source lists -LIBNAME=hprof -SOURCES= \ - debug_malloc.c \ - hprof_blocks.c \ - hprof_class.c \ - hprof_cpu.c \ - hprof_error.c \ - hprof_event.c \ - hprof_frame.c \ - hprof_init.c \ - hprof_io.c \ - hprof_ioname.c \ - hprof_listener.c \ - hprof_loader.c \ - hprof_monitor.c \ - hprof_object.c \ - hprof_reference.c \ - hprof_site.c \ - hprof_stack.c \ - hprof_string.c \ - hprof_table.c \ - hprof_tag.c \ - hprof_tls.c \ - hprof_trace.c \ - hprof_tracker.c \ - hprof_util.c \ - hprof_md.c - -JAVA_SOURCES=Tracker.java - -# Name of jar file that needs to be created -#JARFILE=hprof.jar - -# Solaris Sun C Compiler Version 5.5 -ifeq ($(OSNAME), solaris) - # Sun Solaris Compiler options needed - COMMON_FLAGS=-mt -KPIC - # Options that help find errors - COMMON_FLAGS+= -Xa -v -xstrconst -xc99=%none - # To make hprof logging code available - COMMON_FLAGS+= -DHPROF_LOGGING - # Check LIBARCH for any special compiler options - LIBARCH=$(shell uname -p) - ifeq ($(LIBARCH), sparc) - COMMON_FLAGS+=-xarch=v8 -xregs=no%appl - endif - ifeq ($(LIBARCH), sparcv9) - COMMON_FLAGS+=-xarch=v9 -xregs=no%appl - endif - ifeq ($(OPT), true) - CFLAGS=-xO2 $(COMMON_FLAGS) -DNDEBUG - else - CFLAGS=-g $(COMMON_FLAGS) -DDEBUG - endif - # Object files needed to create library - OBJECTS=$(SOURCES:%.c=%.o) - # Library name and options needed to build it - LIBRARY=lib$(LIBNAME).so - LDFLAGS=-z defs -ztext - # Libraries we are dependent on - LIBRARIES=-lsocket -lnsl -ldl -lc - # Building a shared library - LINK_SHARED=$(LINK.c) -G -o $@ -endif - -# Linux GNU C Compiler -ifeq ($(OSNAME), linux) - # GNU Compiler options needed to build it - COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer - # Options that help find errors - COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses - # To allow access to dladdr() - COMMON_FLAGS+= -D_GNU_SOURCE - # To prevent include of procfs.h - COMMON_FLAGS+= -DLINUX - # To make sure code is reentrant - COMMON_FLAGS+= -D_REENTRANT - # To make hprof logging code available - COMMON_FLAGS+= -DHPROF_LOGGING - ifeq ($(OPT), true) - CFLAGS=-O2 $(COMMON_FLAGS) -DNDEBUG - else - CFLAGS=-g $(COMMON_FLAGS) -DDEBUG - endif - # Object files needed to create library - OBJECTS=$(SOURCES:%.c=%.o) - # Library name and options needed to build it - LIBRARY=lib$(LIBNAME).so - LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc - # Libraries we are dependent on - LIBRARIES= -ldl -lc - # Building a shared library - LINK_SHARED=$(LINK.c) -shared -o $@ -endif - -# Windows Microsoft C/C++ Optimizing Compiler Version 12 -ifeq ($(OSNAME), win32) - CC=cl - # Compiler options needed to build it - COMMON_FLAGS=-Gy -DWIN32 - # Options that help find errors - COMMON_FLAGS+=-W0 -WX - # To make hprof logging code available - COMMON_FLAGS+= -DHPROF_LOGGING - ifeq ($(OPT), true) - CFLAGS= -Ox -Op -Zi $(COMMON_FLAGS) -DNDEBUG - else - CFLAGS= -Od -Zi $(COMMON_FLAGS) -DDEBUG - endif - # Add java_crw_demo source - SOURCES += ../java_crw_demo.c - # Object files needed to create library - OBJECTS=$(SOURCES:%.c=%.obj) - # Library name and options needed to build it - LIBRARY=$(LIBNAME).dll - LDFLAGS= - # Libraries we are dependent on - LIBRARIES=wsock32.lib winmm.lib - # Building a shared library - LINK_SHARED=link -dll -out:$@ -endif - -# Common -I options -CFLAGS += -I. -CFLAGS += -I../java_crw_demo -CFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME) - -# Default rule (build both native library and jar file) -all: hprof_md.c $(LIBRARY) $(JARFILE) - -# Get platform specific hprof_md.c -hprof_md.c: - rm -f $@ - cp $(OSNAME)/hprof_md.c $@ - -# Build native library -$(LIBRARY): $(OBJECTS) - $(LINK_SHARED) $(OBJECTS) $(LIBRARIES) - -# Build jar file -$(JARFILE): $(JAVA_SOURCES) - rm -f -r classes - mkdir -p classes - $(JDK)/bin/javac -d classes $(JAVA_SOURCES) - (cd classes; $(JDK)/bin/jar cf ../$@ *) - -# Cleanup the built bits -clean: - rm -f -r classes - rm -f $(LIBRARY) $(JARFILE) $(OBJECTS) - -# Simple tester -test: all - LD_LIBRARY_PATH=. $(JDK)/bin/java -agentlib:$(LIBNAME) -Xbootclasspath/a:./$(JARFILE) -version - -# Compilation rule only needed on Windows -ifeq ($(OSNAME), win32) -%.obj: %.c - $(COMPILE.c) $< -endif - diff --git a/jdk/src/demo/share/jvmti/index.html b/jdk/src/demo/share/jvmti/index.html index b66ac8d9bfa..4b479c12468 100644 --- a/jdk/src/demo/share/jvmti/index.html +++ b/jdk/src/demo/share/jvmti/index.html @@ -54,17 +54,16 @@ variable (Windows). This is system and platform specific. If you are using 64bit Solaris (e.g. 'java -d64'), you should use LD_LIBRARY_PATH64. -Some agents such as hprof (heap/cpu profiler) and jdwp (debugger backend) +Some agents such as the jdwp (debugger backend) are located inside the primary JDK directories and will always be found in those locations.

The agents that instrument classfiles (i.e. BCI, usually through the java_crw_demo library) -such as hprof, heapTracker, mtrace, and minst, +such as heapTracker, mtrace, and minst, also need to have the Java classes they use available in the bootclasspath. -The one used by hprof is already in the bootclasspath, and the -other agents will make attempts at automatically adding their jar file +The agents will make attempts at automatically adding their jar file (e.g. heapTracker.jar, mtrace.jar, or minst.jar) to the bootclasspath with AddToBootstrapClassLoaderSearch from JVM TI at startup (see the agent_util code). @@ -150,19 +149,6 @@ This is a small agent that gets information about threads waiting on monitors. -

  • -hprof -
    -This is a large agent that does heap and cpu profiling. -This demo agent is actually built into the - -Java Runtime Environment (JRE). -It uses Bytecode Instrumentation (BCI) via the java_crw_demo library. -
    -Note: hprof is NOT a small or simple agent, the other smaller demos -should be looked at first. -
  • - diff --git a/jdk/src/java.base/share/classes/java/io/ByteArrayOutputStream.java b/jdk/src/java.base/share/classes/java/io/ByteArrayOutputStream.java index 71be2db3b47..3d199579249 100644 --- a/jdk/src/java.base/share/classes/java/io/ByteArrayOutputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ByteArrayOutputStream.java @@ -93,6 +93,14 @@ public class ByteArrayOutputStream extends OutputStream { grow(minCapacity); } + /** + * The maximum size of array to allocate. + * Some VMs reserve some header words in an array. + * Attempts to allocate larger arrays may result in + * OutOfMemoryError: Requested array size exceeds VM limit + */ + private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8; + /** * Increases the capacity to ensure that it can hold at least the * number of elements specified by the minimum capacity argument. @@ -105,14 +113,19 @@ public class ByteArrayOutputStream extends OutputStream { int newCapacity = oldCapacity << 1; if (newCapacity - minCapacity < 0) newCapacity = minCapacity; - if (newCapacity < 0) { - if (minCapacity < 0) // overflow - throw new OutOfMemoryError(); - newCapacity = Integer.MAX_VALUE; - } + if (newCapacity - MAX_ARRAY_SIZE > 0) + newCapacity = hugeCapacity(minCapacity); buf = Arrays.copyOf(buf, newCapacity); } + private static int hugeCapacity(int minCapacity) { + if (minCapacity < 0) // overflow + throw new OutOfMemoryError(); + return (minCapacity > MAX_ARRAY_SIZE) ? + Integer.MAX_VALUE : + MAX_ARRAY_SIZE; + } + /** * Writes the specified byte to this byte array output stream. * diff --git a/jdk/src/java.base/share/classes/java/io/FileInputStream.java b/jdk/src/java.base/share/classes/java/io/FileInputStream.java index 6f13156bf98..b501b45707f 100644 --- a/jdk/src/java.base/share/classes/java/io/FileInputStream.java +++ b/jdk/src/java.base/share/classes/java/io/FileInputStream.java @@ -184,7 +184,16 @@ class FileInputStream extends InputStream * Opens the specified file for reading. * @param name the name of the file */ - private native void open(String name) throws FileNotFoundException; + private native void open0(String name) throws FileNotFoundException; + + // wrap native call to allow instrumentation + /** + * Opens the specified file for reading. + * @param name the name of the file + */ + private void open(String name) throws FileNotFoundException { + open0(name); + } /** * Reads a byte of data from this input stream. This method blocks diff --git a/jdk/src/java.base/share/classes/java/io/FileOutputStream.java b/jdk/src/java.base/share/classes/java/io/FileOutputStream.java index 1f7cff54cfa..281a695e6df 100644 --- a/jdk/src/java.base/share/classes/java/io/FileOutputStream.java +++ b/jdk/src/java.base/share/classes/java/io/FileOutputStream.java @@ -256,9 +256,20 @@ class FileOutputStream extends OutputStream * @param name name of file to be opened * @param append whether the file is to be opened in append mode */ - private native void open(String name, boolean append) + private native void open0(String name, boolean append) throws FileNotFoundException; + // wrap native call to allow instrumentation + /** + * Opens a file, with the specified name, for overwriting or appending. + * @param name name of file to be opened + * @param append whether the file is to be opened in append mode + */ + private void open(String name, boolean append) + throws FileNotFoundException { + open0(name, append); + } + /** * Writes the specified byte to this file output stream. * diff --git a/jdk/src/java.base/share/classes/java/io/FilePermission.java b/jdk/src/java.base/share/classes/java/io/FilePermission.java index 0744ea28e4a..b008d4f933a 100644 --- a/jdk/src/java.base/share/classes/java/io/FilePermission.java +++ b/jdk/src/java.base/share/classes/java/io/FilePermission.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -31,6 +31,7 @@ import java.util.List; import java.util.ArrayList; import java.util.Vector; import java.util.Collections; +import java.util.StringJoiner; import sun.security.util.SecurityConstants; /** @@ -556,39 +557,25 @@ public final class FilePermission extends Permission implements Serializable { * @return the canonical string representation of the actions. */ private static String getActions(int mask) { - StringBuilder sb = new StringBuilder(); - boolean comma = false; + StringJoiner sj = new StringJoiner(","); if ((mask & READ) == READ) { - comma = true; - sb.append("read"); + sj.add("read"); } - if ((mask & WRITE) == WRITE) { - if (comma) sb.append(','); - else comma = true; - sb.append("write"); + sj.add("write"); } - if ((mask & EXECUTE) == EXECUTE) { - if (comma) sb.append(','); - else comma = true; - sb.append("execute"); + sj.add("execute"); } - if ((mask & DELETE) == DELETE) { - if (comma) sb.append(','); - else comma = true; - sb.append("delete"); + sj.add("delete"); } - if ((mask & READLINK) == READLINK) { - if (comma) sb.append(','); - else comma = true; - sb.append("readlink"); + sj.add("readlink"); } - return sb.toString(); + return sj.toString(); } /** diff --git a/jdk/src/java.base/share/classes/java/io/ObjectOutputStream.java b/jdk/src/java.base/share/classes/java/io/ObjectOutputStream.java index 7dc6dde469f..e99e0257f31 100644 --- a/jdk/src/java.base/share/classes/java/io/ObjectOutputStream.java +++ b/jdk/src/java.base/share/classes/java/io/ObjectOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -32,6 +32,7 @@ import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.StringJoiner; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; import static java.io.ObjectStreamClass.processQueue; @@ -2465,15 +2466,11 @@ public class ObjectOutputStream * Returns a string representation of this object */ public String toString() { - StringBuilder buffer = new StringBuilder(); - if (!stack.isEmpty()) { - for(int i = stack.size(); i > 0; i-- ) { - buffer.append(stack.get(i - 1)); - if (i != 1) - buffer.append('\n'); - } + StringJoiner sj = new StringJoiner("\n"); + for (int i = stack.size() - 1; i >= 0; i--) { + sj.add(stack.get(i)); } - return buffer.toString(); + return sj.toString(); } } diff --git a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java index ae1e530f168..d6b79b245cd 100644 --- a/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/jdk/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -296,9 +296,26 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * @param mode the mode flags, a combination of the O_ constants * defined above */ - private native void open(String name, int mode) + private native void open0(String name, int mode) throws FileNotFoundException; + // wrap native call to allow instrumentation + /** + * Opens a file and returns the file descriptor. The file is + * opened in read-write mode if the O_RDWR bit in {@code mode} + * is true, else the file is opened as read-only. + * If the {@code name} refers to a directory, an IOException + * is thrown. + * + * @param name the name of the file + * @param mode the mode flags, a combination of the O_ constants + * defined above + */ + private void open(String name, int mode) + throws FileNotFoundException { + open0(name, mode); + } + // 'Read' primitives /** diff --git a/jdk/src/java.base/share/classes/java/lang/Class.java b/jdk/src/java.base/share/classes/java/lang/Class.java index cd26ab11791..2179ee809f5 100644 --- a/jdk/src/java.base/share/classes/java/lang/Class.java +++ b/jdk/src/java.base/share/classes/java/lang/Class.java @@ -54,6 +54,7 @@ import java.util.Set; import java.util.Map; import java.util.HashMap; import java.util.Objects; +import java.util.StringJoiner; import sun.misc.Unsafe; import sun.reflect.CallerSensitive; import sun.reflect.ConstantPool; @@ -1322,7 +1323,7 @@ public final class Class implements java.io.Serializable, // (for anonymous classes): 1 or more digits. // Since getSimpleBinaryName() will strip the binary name of - // the immediatly enclosing class, we are now looking at a + // the immediately enclosing class, we are now looking at a // string that matches the regular expression "\$[0-9]*" // followed by a simple name (considering the simple of an // anonymous class to be the empty string). @@ -3141,19 +3142,14 @@ public final class Class implements java.io.Serializable, private native Class[] getDeclaredClasses0(); private static String argumentTypesToString(Class[] argTypes) { - StringBuilder buf = new StringBuilder(); - buf.append("("); + StringJoiner sj = new StringJoiner(", ", "(", ")"); if (argTypes != null) { for (int i = 0; i < argTypes.length; i++) { - if (i > 0) { - buf.append(", "); - } Class c = argTypes[i]; - buf.append((c == null) ? "null" : c.getName()); + sj.add((c == null) ? "null" : c.getName()); } } - buf.append(")"); - return buf.toString(); + return sj.toString(); } /** use serialVersionUID from JDK 1.1 for interoperability */ diff --git a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java index 1652d6cc4eb..1def66a146b 100644 --- a/jdk/src/java.base/share/classes/java/lang/ClassLoader.java +++ b/jdk/src/java.base/share/classes/java/lang/ClassLoader.java @@ -205,7 +205,7 @@ public abstract class ClassLoader { } /** - * Registers the given class loader type as parallel capabale. + * Registers the given class loader type as parallel capable. * Returns {@code true} is successfully registered; {@code false} if * loader's super class is not registered. */ @@ -832,7 +832,7 @@ public abstract class ClassLoader { { int len = b.remaining(); - // Use byte[] if not a direct ByteBufer: + // Use byte[] if not a direct ByteBuffer: if (!b.isDirect()) { if (b.hasArray()) { return defineClass(name, b.array(), diff --git a/jdk/src/java.base/share/classes/java/lang/Integer.java b/jdk/src/java.base/share/classes/java/lang/Integer.java index 94b0aff7970..d22ce9bef35 100644 --- a/jdk/src/java.base/share/classes/java/lang/Integer.java +++ b/jdk/src/java.base/share/classes/java/lang/Integer.java @@ -592,37 +592,6 @@ public final class Integer extends Number implements Comparable { } } - /** - * Parses the {@link CharSequence} argument as a signed {@code int} in the - * specified {@code radix}, beginning at the specified {@code beginIndex} - * and extending to the end of the sequence. - * - *

    The method does not take steps to guard against the - * {@code CharSequence} being mutated while parsing. - * - * @param s the {@code CharSequence} containing the {@code int} - * representation to be parsed - * @param radix the radix to be used while parsing {@code s}. - * @param beginIndex the beginning index, inclusive. - * @return the signed {@code int} represented by the subsequence in - * the specified radix. - * @throws NullPointerException if {@code s} is null. - * @throws IndexOutOfBoundsException if {@code beginIndex} is - * negative, or if {@code beginIndex} is greater than - * {@code s.length()}. - * @throws NumberFormatException if the {@code CharSequence} does not - * contain a parsable {@code int} in the specified - * {@code radix}, or if {@code radix} is either smaller than - * {@link java.lang.Character#MIN_RADIX} or larger than - * {@link java.lang.Character#MAX_RADIX}. - * @since 1.9 - */ - public static int parseInt(CharSequence s, int radix, int beginIndex) - throws NumberFormatException { - // forces an implicit null check of s - return parseInt(s, radix, beginIndex, s.length()); - } - /** * Parses the {@link CharSequence} argument as a signed {@code int} in the * specified {@code radix}, beginning at the specified {@code beginIndex} @@ -633,9 +602,9 @@ public final class Integer extends Number implements Comparable { * * @param s the {@code CharSequence} containing the {@code int} * representation to be parsed - * @param radix the radix to be used while parsing {@code s}. * @param beginIndex the beginning index, inclusive. * @param endIndex the ending index, exclusive. + * @param radix the radix to be used while parsing {@code s}. * @return the signed {@code int} represented by the subsequence in * the specified radix. * @throws NullPointerException if {@code s} is null. @@ -650,7 +619,7 @@ public final class Integer extends Number implements Comparable { * {@link java.lang.Character#MAX_RADIX}. * @since 1.9 */ - public static int parseInt(CharSequence s, int radix, int beginIndex, int endIndex) + public static int parseInt(CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException { s = Objects.requireNonNull(s); @@ -690,7 +659,7 @@ public final class Integer extends Number implements Comparable { int result = 0; while (i < endIndex) { // Accumulating negatively avoids surprises near MAX_VALUE - int digit = Character.digit(s.charAt(i++), radix); + int digit = Character.digit(s.charAt(i), radix); if (digit < 0 || result < multmin) { throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i); @@ -700,6 +669,7 @@ public final class Integer extends Number implements Comparable { throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i); } + i++; result -= digit; } return negative ? result : -result; @@ -805,37 +775,6 @@ public final class Integer extends Number implements Comparable { } } - /** - * Parses the {@link CharSequence} argument as an unsigned {@code int} in - * the specified {@code radix}, beginning at the specified - * {@code beginIndex} and extending to the end of the sequence. - * - *

    The method does not take steps to guard against the - * {@code CharSequence} being mutated while parsing. - * - * @param s the {@code CharSequence} containing the unsigned - * {@code int} representation to be parsed - * @param radix the radix to be used while parsing {@code s}. - * @param beginIndex the beginning index, inclusive. - * @return the unsigned {@code int} represented by the subsequence in - * the specified radix. - * @throws NullPointerException if {@code s} is null. - * @throws IndexOutOfBoundsException if {@code beginIndex} is - * negative, or if {@code beginIndex} is greater than - * {@code s.length()}. - * @throws NumberFormatException if the {@code CharSequence} does not - * contain a parsable unsigned {@code int} in the specified - * {@code radix}, or if {@code radix} is either smaller than - * {@link java.lang.Character#MIN_RADIX} or larger than - * {@link java.lang.Character#MAX_RADIX}. - * @since 1.9 - */ - public static int parseUnsignedInt(CharSequence s, int radix, int beginIndex) - throws NumberFormatException { - // forces an implicit null check of s - return parseUnsignedInt(s, radix, beginIndex, s.length()); - } - /** * Parses the {@link CharSequence} argument as an unsigned {@code int} in * the specified {@code radix}, beginning at the specified @@ -846,9 +785,9 @@ public final class Integer extends Number implements Comparable { * * @param s the {@code CharSequence} containing the unsigned * {@code int} representation to be parsed - * @param radix the radix to be used while parsing {@code s}. * @param beginIndex the beginning index, inclusive. * @param endIndex the ending index, exclusive. + * @param radix the radix to be used while parsing {@code s}. * @return the unsigned {@code int} represented by the subsequence in * the specified radix. * @throws NullPointerException if {@code s} is null. @@ -863,7 +802,7 @@ public final class Integer extends Number implements Comparable { * {@link java.lang.Character#MAX_RADIX}. * @since 1.9 */ - public static int parseUnsignedInt(CharSequence s, int radix, int beginIndex, int endIndex) + public static int parseUnsignedInt(CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException { s = Objects.requireNonNull(s); @@ -881,9 +820,9 @@ public final class Integer extends Number implements Comparable { } else { if (len <= 5 || // Integer.MAX_VALUE in Character.MAX_RADIX is 6 digits (radix == 10 && len <= 9)) { // Integer.MAX_VALUE in base 10 is 10 digits - return parseInt(s, radix, start, start + len); + return parseInt(s, start, start + len, radix); } else { - long ell = Long.parseLong(s, radix, start, start + len); + long ell = Long.parseLong(s, start, start + len, radix); if ((ell & 0xffff_ffff_0000_0000L) == 0) { return (int) ell; } else { diff --git a/jdk/src/java.base/share/classes/java/lang/Long.java b/jdk/src/java.base/share/classes/java/lang/Long.java index 76caa77fac7..bcf33fccff8 100644 --- a/jdk/src/java.base/share/classes/java/lang/Long.java +++ b/jdk/src/java.base/share/classes/java/lang/Long.java @@ -604,37 +604,6 @@ public final class Long extends Number implements Comparable { } } - /** - * Parses the {@link CharSequence} argument as a signed {@code long} in - * the specified {@code radix}, beginning at the specified {@code beginIndex} - * and extending to the end of the sequence. - * - *

    The method does not take steps to guard against the - * {@code CharSequence} being mutated while parsing. - * - * @param s the {@code CharSequence} containing the {@code long} - * representation to be parsed - * @param radix the radix to be used while parsing {@code s}. - * @param beginIndex the beginning index, inclusive. - * @return the signed {@code long} represented by the subsequence in - * the specified radix. - * @throws NullPointerException if {@code s} is null. - * @throws IndexOutOfBoundsException if {@code beginIndex} is - * negative, or if {@code beginIndex} is greater than - * {@code s.length()}. - * @throws NumberFormatException if the {@code CharSequence} does not - * contain a parsable {@code long} in the specified - * {@code radix}, or if {@code radix} is either smaller than - * {@link java.lang.Character#MIN_RADIX} or larger than - * {@link java.lang.Character#MAX_RADIX}. - * @since 1.9 - */ - public static long parseLong(CharSequence s, int radix, int beginIndex) - throws NumberFormatException { - // forces a null check of s - return parseLong(s, radix, beginIndex, s.length()); - } - /** * Parses the {@link CharSequence} argument as a signed {@code long} in * the specified {@code radix}, beginning at the specified @@ -645,9 +614,9 @@ public final class Long extends Number implements Comparable { * * @param s the {@code CharSequence} containing the {@code long} * representation to be parsed - * @param radix the radix to be used while parsing {@code s}. * @param beginIndex the beginning index, inclusive. * @param endIndex the ending index, exclusive. + * @param radix the radix to be used while parsing {@code s}. * @return the signed {@code long} represented by the subsequence in * the specified radix. * @throws NullPointerException if {@code s} is null. @@ -662,7 +631,7 @@ public final class Long extends Number implements Comparable { * {@link java.lang.Character#MAX_RADIX}. * @since 1.9 */ - public static long parseLong(CharSequence s, int radix, int beginIndex, int endIndex) + public static long parseLong(CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException { s = Objects.requireNonNull(s); @@ -702,7 +671,7 @@ public final class Long extends Number implements Comparable { long result = 0; while (i < endIndex) { // Accumulating negatively avoids surprises near MAX_VALUE - int digit = Character.digit(s.charAt(i++), radix); + int digit = Character.digit(s.charAt(i), radix); if (digit < 0 || result < multmin) { throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i); @@ -712,6 +681,7 @@ public final class Long extends Number implements Comparable { throw NumberFormatException.forCharSequence(s, beginIndex, endIndex, i); } + i++; result -= digit; } return negative ? result : -result; @@ -811,7 +781,7 @@ public final class Long extends Number implements Comparable { } // No need for range checks on len due to testing above. - long first = parseLong(s, radix, 0, len - 1); + long first = parseLong(s, 0, len - 1, radix); int second = Character.digit(s.charAt(len - 1), radix); if (second < 0) { throw new NumberFormatException("Bad digit at end of " + s); @@ -880,37 +850,6 @@ public final class Long extends Number implements Comparable { } } - /** - * Parses the {@link CharSequence} argument as an unsigned {@code long} in - * the specified {@code radix}, beginning at the specified - * {@code beginIndex} and extending to the end of the sequence. - * - *

    The method does not take steps to guard against the - * {@code CharSequence} being mutated while parsing. - * - * @param s the {@code CharSequence} containing the unsigned - * {@code long} representation to be parsed - * @param radix the radix to be used while parsing {@code s}. - * @param beginIndex the beginning index, inclusive. - * @return the unsigned {@code long} represented by the subsequence in - * the specified radix. - * @throws NullPointerException if {@code s} is null. - * @throws IndexOutOfBoundsException if {@code beginIndex} is - * negative, or if {@code beginIndex} is greater than - * {@code s.length()}. - * @throws NumberFormatException if the {@code CharSequence} does not - * contain a parsable unsigned {@code long} in the specified - * {@code radix}, or if {@code radix} is either smaller than - * {@link java.lang.Character#MIN_RADIX} or larger than - * {@link java.lang.Character#MAX_RADIX}. - * @since 1.9 - */ - public static long parseUnsignedLong(CharSequence s, int radix, int beginIndex) - throws NumberFormatException { - // forces a null check of s - return parseUnsignedLong(s, radix, beginIndex, s.length()); - } - /** * Parses the {@link CharSequence} argument as an unsigned {@code long} in * the specified {@code radix}, beginning at the specified @@ -921,9 +860,9 @@ public final class Long extends Number implements Comparable { * * @param s the {@code CharSequence} containing the unsigned * {@code long} representation to be parsed - * @param radix the radix to be used while parsing {@code s}. * @param beginIndex the beginning index, inclusive. * @param endIndex the ending index, exclusive. + * @param radix the radix to be used while parsing {@code s}. * @return the unsigned {@code long} represented by the subsequence in * the specified radix. * @throws NullPointerException if {@code s} is null. @@ -938,7 +877,7 @@ public final class Long extends Number implements Comparable { * {@link java.lang.Character#MAX_RADIX}. * @since 1.9 */ - public static long parseUnsignedLong(CharSequence s, int radix, int beginIndex, int endIndex) + public static long parseUnsignedLong(CharSequence s, int beginIndex, int endIndex, int radix) throws NumberFormatException { s = Objects.requireNonNull(s); @@ -955,11 +894,11 @@ public final class Long extends Number implements Comparable { } else { if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits - return parseLong(s, radix, start, start + len); + return parseLong(s, start, start + len, radix); } // No need for range checks on end due to testing above. - long first = parseLong(s, radix, start, start + len - 1); + long first = parseLong(s, start, start + len - 1, radix); int second = Character.digit(s.charAt(start + len - 1), radix); if (second < 0) { throw new NumberFormatException("Bad digit at end of " + diff --git a/jdk/src/java.base/share/classes/java/lang/String.java b/jdk/src/java.base/share/classes/java/lang/String.java index ce673fba2d4..00f57044624 100644 --- a/jdk/src/java.base/share/classes/java/lang/String.java +++ b/jdk/src/java.base/share/classes/java/lang/String.java @@ -2119,7 +2119,7 @@ public final class String * @since 1.5 */ public boolean contains(CharSequence s) { - return indexOf(s.toString()) > -1; + return indexOf(s.toString()) >= 0; } /** diff --git a/jdk/src/java.base/share/classes/java/lang/StringCoding.java b/jdk/src/java.base/share/classes/java/lang/StringCoding.java index 24ed0c06bbe..a4c71b4cf21 100644 --- a/jdk/src/java.base/share/classes/java/lang/StringCoding.java +++ b/jdk/src/java.base/share/classes/java/lang/StringCoding.java @@ -196,19 +196,19 @@ class StringCoding { static char[] decode(Charset cs, byte[] ba, int off, int len) { // (1)We never cache the "external" cs, the only benefit of creating // an additional StringDe/Encoder object to wrap it is to share the - // de/encode() method. These SD/E objects are short-lifed, the young-gen - // gc should be able to take care of them well. But the best approash + // de/encode() method. These SD/E objects are short-lived, the young-gen + // gc should be able to take care of them well. But the best approach // is still not to generate them if not really necessary. // (2)The defensive copy of the input byte/char[] has a big performance // impact, as well as the outgoing result byte/char[]. Need to do the // optimization check of (sm==null && classLoader0==null) for both. // (3)getClass().getClassLoader0() is expensive // (4)There might be a timing gap in isTrusted setting. getClassLoader0() - // is only chcked (and then isTrusted gets set) when (SM==null). It is + // is only checked (and then isTrusted gets set) when (SM==null). It is // possible that the SM==null for now but then SM is NOT null later // when safeTrim() is invoked...the "safe" way to do is to redundant // check (... && (isTrusted || SM == null || getClassLoader0())) in trim - // but it then can be argued that the SM is null when the opertaion + // but it then can be argued that the SM is null when the operation // is started... CharsetDecoder cd = cs.newDecoder(); int en = scale(len, cd.maxCharsPerByte()); diff --git a/jdk/src/java.base/share/classes/java/lang/System.java b/jdk/src/java.base/share/classes/java/lang/System.java index fbac697c245..345cdae1df7 100644 --- a/jdk/src/java.base/share/classes/java/lang/System.java +++ b/jdk/src/java.base/share/classes/java/lang/System.java @@ -1193,7 +1193,7 @@ public final class System { // Setup Java signal handlers for HUP, TERM, and INT (where available). Terminator.setup(); - // Initialize any miscellenous operating system settings that need to be + // Initialize any miscellaneous operating system settings that need to be // set for the class libraries. Currently this is no-op everywhere except // for Windows where the process-wide error mode is set before the java.io // classes are used. diff --git a/jdk/src/java.base/share/classes/java/lang/Throwable.java b/jdk/src/java.base/share/classes/java/lang/Throwable.java index 396d8e90ecc..d71f9ecdf0d 100644 --- a/jdk/src/java.base/share/classes/java/lang/Throwable.java +++ b/jdk/src/java.base/share/classes/java/lang/Throwable.java @@ -139,7 +139,7 @@ public class Throwable implements Serializable { * {@linkplain #setStackTrace(StackTraceElement[]) Setting the * stack trace} to a one-element array containing this sentinel * value indicates future attempts to set the stack trace will be - * ignored. The sentinal is equal to the result of calling:
    + * ignored. The sentinel is equal to the result of calling:
    * {@code new StackTraceElement("", "", null, Integer.MIN_VALUE)} */ public static final StackTraceElement STACK_TRACE_ELEMENT_SENTINEL = diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java index f860c77e5e2..74f53e47906 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java @@ -50,31 +50,31 @@ import jdk.internal.org.objectweb.asm.Type; * * All bound arguments are encapsulated in dedicated species. */ -/* non-public */ abstract class BoundMethodHandle extends MethodHandle { +/*non-public*/ abstract class BoundMethodHandle extends MethodHandle { - /* non-public */ BoundMethodHandle(MethodType type, LambdaForm form) { + /*non-public*/ BoundMethodHandle(MethodType type, LambdaForm form) { super(type, form); + assert(speciesData() == speciesData(form)); } // // BMH API and internals // - static MethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) { + static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) { // for some type signatures, there exist pre-defined concrete BMH classes try { switch (xtype) { case L_TYPE: - if (true) return bindSingle(type, form, x); // Use known fast path. - return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(L_TYPE).constructor[0].invokeBasic(type, form, x); + return bindSingle(type, form, x); // Use known fast path. case I_TYPE: - return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor[0].invokeBasic(type, form, ValueConversions.widenSubword(x)); + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(I_TYPE).constructor().invokeBasic(type, form, ValueConversions.widenSubword(x)); case J_TYPE: - return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor[0].invokeBasic(type, form, (long) x); + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(J_TYPE).constructor().invokeBasic(type, form, (long) x); case F_TYPE: - return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor[0].invokeBasic(type, form, (float) x); + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(F_TYPE).constructor().invokeBasic(type, form, (float) x); case D_TYPE: - return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor[0].invokeBasic(type, form, (double) x); + return (BoundMethodHandle) SpeciesData.EMPTY.extendWith(D_TYPE).constructor().invokeBasic(type, form, (double) x); default : throw newInternalError("unexpected xtype: " + xtype); } } catch (Throwable t) { @@ -82,49 +82,61 @@ import jdk.internal.org.objectweb.asm.Type; } } - static MethodHandle bindSingle(MethodType type, LambdaForm form, Object x) { - return new Species_L(type, form, x); + /*non-public*/ + LambdaFormEditor editor() { + return form.editor(); } - MethodHandle cloneExtend(MethodType type, LambdaForm form, BasicType xtype, Object x) { - try { - switch (xtype) { - case L_TYPE: return copyWithExtendL(type, form, x); - case I_TYPE: return copyWithExtendI(type, form, ValueConversions.widenSubword(x)); - case J_TYPE: return copyWithExtendJ(type, form, (long) x); - case F_TYPE: return copyWithExtendF(type, form, (float) x); - case D_TYPE: return copyWithExtendD(type, form, (double) x); - } - } catch (Throwable t) { - throw newInternalError(t); + static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, Object x) { + return Species_L.make(type, form, x); + } + + @Override // there is a default binder in the super class, for 'L' types only + /*non-public*/ + BoundMethodHandle bindArgumentL(int pos, Object value) { + return editor().bindArgumentL(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentI(int pos, int value) { + return editor().bindArgumentI(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentJ(int pos, long value) { + return editor().bindArgumentJ(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentF(int pos, float value) { + return editor().bindArgumentF(this, pos, value); + } + /*non-public*/ + BoundMethodHandle bindArgumentD(int pos, double value) { + return editor().bindArgumentD(this, pos, value); + } + + @Override + BoundMethodHandle rebind() { + if (!tooComplex()) { + return this; } - throw newInternalError("unexpected type: " + xtype); + return makeReinvoker(this); } - @Override - MethodHandle bindArgument(int pos, BasicType basicType, Object value) { - MethodType type = type().dropParameterTypes(pos, pos+1); - LambdaForm form = internalForm().bind(1+pos, speciesData()); - return cloneExtend(type, form, basicType, value); + private boolean tooComplex() { + return (fieldCount() > FIELD_COUNT_THRESHOLD || + form.expressionCount() > FORM_EXPRESSION_THRESHOLD); } + private static final int FIELD_COUNT_THRESHOLD = 12; // largest convenient BMH field count + private static final int FORM_EXPRESSION_THRESHOLD = 24; // largest convenient BMH expression count - @Override - MethodHandle dropArguments(MethodType srcType, int pos, int drops) { - LambdaForm form = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos + drops)); - try { - return copyWith(srcType, form); - } catch (Throwable t) { - throw newInternalError(t); - } - } - - @Override - MethodHandle permuteArguments(MethodType newType, int[] reorder) { - try { - return copyWith(newType, form.permuteArguments(1, reorder, basicTypes(newType.parameterList()))); - } catch (Throwable t) { - throw newInternalError(t); - } + /** + * A reinvoker MH has this form: + * {@code lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) }} + */ + static BoundMethodHandle makeReinvoker(MethodHandle target) { + LambdaForm form = DelegatingMethodHandle.makeReinvokerForm( + target, MethodTypeForm.LF_REBIND, + Species_L.SPECIES_DATA, Species_L.SPECIES_DATA.getterFunction(0)); + return Species_L.make(target.type(), form, target); } /** @@ -133,14 +145,22 @@ import jdk.internal.org.objectweb.asm.Type; */ /*non-public*/ abstract SpeciesData speciesData(); + /*non-public*/ static SpeciesData speciesData(LambdaForm form) { + Object c = form.names[0].constraint; + if (c instanceof SpeciesData) + return (SpeciesData) c; + // if there is no BMH constraint, then use the null constraint + return SpeciesData.EMPTY; + } + /** * Return the number of fields in this BMH. Equivalent to speciesData().fieldCount(). */ /*non-public*/ abstract int fieldCount(); @Override - final Object internalProperties() { - return "/BMH="+internalValues(); + Object internalProperties() { + return "\n& BMH="+internalValues(); } @Override @@ -178,15 +198,6 @@ import jdk.internal.org.objectweb.asm.Type; /*non-public*/ abstract BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg); /*non-public*/ abstract BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg); - // The following is a grossly irregular hack: - @Override MethodHandle reinvokerTarget() { - try { - return (MethodHandle) arg(0); - } catch (Throwable ex) { - throw newInternalError(ex); - } - } - // // concrete BMH classes required to close bootstrap loops // @@ -198,8 +209,6 @@ import jdk.internal.org.objectweb.asm.Type; super(mt, lf); this.argL0 = argL0; } - // The following is a grossly irregular hack: - @Override MethodHandle reinvokerTarget() { return (MethodHandle) argL0; } @Override /*non-public*/ SpeciesData speciesData() { return SPECIES_DATA; @@ -219,7 +228,7 @@ import jdk.internal.org.objectweb.asm.Type; @Override /*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) { try { - return (BoundMethodHandle) SPECIES_DATA.extendWith(L_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg); + return (BoundMethodHandle) SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); } catch (Throwable ex) { throw uncaughtException(ex); } @@ -227,7 +236,7 @@ import jdk.internal.org.objectweb.asm.Type; @Override /*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) { try { - return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg); + return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); } catch (Throwable ex) { throw uncaughtException(ex); } @@ -235,7 +244,7 @@ import jdk.internal.org.objectweb.asm.Type; @Override /*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) { try { - return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg); + return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); } catch (Throwable ex) { throw uncaughtException(ex); } @@ -243,7 +252,7 @@ import jdk.internal.org.objectweb.asm.Type; @Override /*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) { try { - return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg); + return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); } catch (Throwable ex) { throw uncaughtException(ex); } @@ -251,7 +260,7 @@ import jdk.internal.org.objectweb.asm.Type; @Override /*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) { try { - return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor[0].invokeBasic(mt, lf, argL0, narg); + return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, narg); } catch (Throwable ex) { throw uncaughtException(ex); } @@ -268,18 +277,20 @@ import jdk.internal.org.objectweb.asm.Type; * The fields are immutable; their values are fully specified at object construction. * Each BMH type supplies an array of getter functions which may be used in lambda forms. * A BMH is constructed by cloning a shorter BMH and adding one or more new field values. - * As a degenerate and common case, the "shorter BMH" can be missing, and contributes zero prior fields. + * The shortest possible BMH has zero fields; its class is SimpleMethodHandle. + * BMH species are not interrelated by subtyping, even though it would appear that + * a shorter BMH could serve as a supertype of a longer one which extends it. */ static class SpeciesData { - final String typeChars; - final BasicType[] typeCodes; - final Class clazz; + private final String typeChars; + private final BasicType[] typeCodes; + private final Class clazz; // Bootstrapping requires circular relations MH -> BMH -> SpeciesData -> MH // Therefore, we need a non-final link in the chain. Use array elements. - final MethodHandle[] constructor; - final MethodHandle[] getters; - final NamedFunction[] nominalGetters; - final SpeciesData[] extensions; + @Stable private final MethodHandle[] constructor; + @Stable private final MethodHandle[] getters; + @Stable private final NamedFunction[] nominalGetters; + @Stable private final SpeciesData[] extensions; /*non-public*/ int fieldCount() { return typeCodes.length; @@ -290,9 +301,14 @@ import jdk.internal.org.objectweb.asm.Type; /*non-public*/ char fieldTypeChar(int i) { return typeChars.charAt(i); } - + Object fieldSignature() { + return typeChars; + } + public Class fieldHolder() { + return clazz; + } public String toString() { - return "SpeciesData["+(isPlaceholder() ? "" : clazz.getSimpleName())+":"+typeChars+"]"; + return "SpeciesData<"+fieldSignature()+">"; } /** @@ -301,7 +317,20 @@ import jdk.internal.org.objectweb.asm.Type; * getter. */ NamedFunction getterFunction(int i) { - return nominalGetters[i]; + NamedFunction nf = nominalGetters[i]; + assert(nf.memberDeclaringClassOrNull() == fieldHolder()); + assert(nf.returnType() == fieldType(i)); + return nf; + } + + NamedFunction[] getterFunctions() { + return nominalGetters; + } + + MethodHandle[] getterHandles() { return getters; } + + MethodHandle constructor() { + return constructor[0]; } static final SpeciesData EMPTY = new SpeciesData("", BoundMethodHandle.class); @@ -324,7 +353,7 @@ import jdk.internal.org.objectweb.asm.Type; private void initForBootstrap() { assert(!INIT_DONE); - if (constructor[0] == null) { + if (constructor() == null) { String types = typeChars; Factory.makeCtors(clazz, types, this.constructor); Factory.makeGetters(clazz, types, this.getters); @@ -508,19 +537,19 @@ import jdk.internal.org.objectweb.asm.Type; * return new Species_LLI(mt, lf, argL0, argL1, argI2); * } * final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) { - * return SPECIES_DATA.extendWith(L_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * return SPECIES_DATA.extendWith(L_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } * final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) { - * return SPECIES_DATA.extendWith(I_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * return SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } * final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) { - * return SPECIES_DATA.extendWith(J_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * return SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } * final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) { - * return SPECIES_DATA.extendWith(F_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * return SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } * public final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) { - * return SPECIES_DATA.extendWith(D_TYPE).constructor[0].invokeBasic(mt, lf, argL0, argL1, argI2, narg); + * return SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, argL0, argL1, argI2, narg); * } * } *

    @@ -575,16 +604,6 @@ import jdk.internal.org.objectweb.asm.Type; mv.visitMaxs(0, 0); mv.visitEnd(); - // emit implementation of reinvokerTarget() - mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "reinvokerTarget", "()" + MH_SIG, null, null); - mv.visitCode(); - mv.visitVarInsn(ALOAD, 0); - mv.visitFieldInsn(GETFIELD, className, "argL0", JLO_SIG); - mv.visitTypeInsn(CHECKCAST, MH); - mv.visitInsn(ARETURN); - mv.visitMaxs(0, 0); - mv.visitEnd(); - // emit implementation of speciesData() mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "speciesData", MYSPECIES_DATA_SIG, null, null); mv.visitCode(); @@ -653,16 +672,14 @@ import jdk.internal.org.objectweb.asm.Type; char btChar = type.basicTypeChar(); mv = cw.visitMethod(NOT_ACC_PUBLIC + ACC_FINAL, "copyWithExtend" + btChar, makeSignature(String.valueOf(btChar), false), null, E_THROWABLE); mv.visitCode(); - // return SPECIES_DATA.extendWith(t).constructor[0].invokeBasic(mt, lf, argL0, ..., narg) + // return SPECIES_DATA.extendWith(t).constructor().invokeBasic(mt, lf, argL0, ..., narg) // obtain constructor mv.visitFieldInsn(GETSTATIC, className, "SPECIES_DATA", SPECIES_DATA_SIG); int iconstInsn = ICONST_0 + ord; assert(iconstInsn <= ICONST_5); mv.visitInsn(iconstInsn); mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "extendWith", BMHSPECIES_DATA_EWI_SIG, false); - mv.visitFieldInsn(GETFIELD, SPECIES_DATA, "constructor", "[" + MH_SIG); - mv.visitInsn(ICONST_0); - mv.visitInsn(AALOAD); + mv.visitMethodInsn(INVOKEVIRTUAL, SPECIES_DATA, "constructor", "()" + MH_SIG, false); // load mt, lf mv.visitVarInsn(ALOAD, 1); mv.visitVarInsn(ALOAD, 2); diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java index 949364bcec4..10ac1c0716e 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/CallSite.java @@ -102,7 +102,7 @@ public class CallSite { */ /*package-private*/ CallSite(MethodType type) { - target = type.invokers().uninitializedCallSite(); + target = makeUninitializedCallSite(type); } /** @@ -211,27 +211,40 @@ public class CallSite { public abstract MethodHandle dynamicInvoker(); /*non-public*/ MethodHandle makeDynamicInvoker() { - MethodHandle getTarget = GET_TARGET.bindReceiver(this); + MethodHandle getTarget = GET_TARGET.bindArgumentL(0, this); MethodHandle invoker = MethodHandles.exactInvoker(this.type()); return MethodHandles.foldArguments(invoker, getTarget); } private static final MethodHandle GET_TARGET; + private static final MethodHandle THROW_UCS; static { try { GET_TARGET = IMPL_LOOKUP. findVirtual(CallSite.class, "getTarget", MethodType.methodType(MethodHandle.class)); + THROW_UCS = IMPL_LOOKUP. + findStatic(CallSite.class, "uninitializedCallSite", MethodType.methodType(Object.class, Object[].class)); } catch (ReflectiveOperationException e) { throw newInternalError(e); } } /** This guy is rolled into the default target if a MethodType is supplied to the constructor. */ - /*package-private*/ - static Empty uninitializedCallSite() { + private static Object uninitializedCallSite(Object... ignore) { throw new IllegalStateException("uninitialized call site"); } + private MethodHandle makeUninitializedCallSite(MethodType targetType) { + MethodType basicType = targetType.basicType(); + MethodHandle invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_UNINIT_CS); + if (invoker == null) { + invoker = THROW_UCS.asType(basicType); + invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_UNINIT_CS, invoker); + } + // unchecked view is OK since no values will be received or returned + return invoker.viewAsType(targetType, false); + } + // unsafe stuff: private static final long TARGET_OFFSET; static { @@ -319,7 +332,7 @@ public class CallSite { throw new ClassCastException("bootstrap method failed to produce a CallSite"); } if (!site.getTarget().type().equals(type)) - throw new WrongMethodTypeException("wrong type: "+site.getTarget()); + throw wrongTargetType(site.getTarget(), type); } catch (Throwable ex) { BootstrapMethodError bex; if (ex instanceof BootstrapMethodError) diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java new file mode 100644 index 00000000000..63ba8fea5b2 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/invoke/DelegatingMethodHandle.java @@ -0,0 +1,145 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.invoke; + +import java.util.Arrays; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.MethodHandleStatics.*; + +/** + * A method handle whose invocation behavior is determined by a target. + * The delegating MH itself can hold extra "intentions" beyond the simple behavior. + * @author jrose + */ +/*non-public*/ +abstract class DelegatingMethodHandle extends MethodHandle { + protected DelegatingMethodHandle(MethodHandle target) { + this(target.type(), target); + } + + protected DelegatingMethodHandle(MethodType type, MethodHandle target) { + super(type, chooseDelegatingForm(target)); + } + + /** Define this to extract the delegated target which supplies the invocation behavior. */ + abstract protected MethodHandle getTarget(); + + @Override + abstract MethodHandle asTypeUncached(MethodType newType); + + @Override + MemberName internalMemberName() { + return getTarget().internalMemberName(); + } + + @Override + boolean isInvokeSpecial() { + return getTarget().isInvokeSpecial(); + } + + @Override + Class internalCallerClass() { + return getTarget().internalCallerClass(); + } + + @Override + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + // FIXME: rethink 'copyWith' protocol; it is too low-level for use on all MHs + throw newIllegalArgumentException("do not use this"); + } + + @Override + String internalProperties() { + return "\n& Class="+getClass().getSimpleName()+ + "\n& Target="+getTarget().debugString(); + } + + @Override + BoundMethodHandle rebind() { + return getTarget().rebind(); + } + + private static LambdaForm chooseDelegatingForm(MethodHandle target) { + if (target instanceof SimpleMethodHandle) + return target.internalForm(); // no need for an indirection + return makeReinvokerForm(target, MethodTypeForm.LF_DELEGATE, DelegatingMethodHandle.class, NF_getTarget); + } + + /** Create a LF which simply reinvokes a target of the given basic type. */ + static LambdaForm makeReinvokerForm(MethodHandle target, + int whichCache, + Object constraint, + NamedFunction getTargetFn) { + MethodType mtype = target.type().basicType(); + boolean customized = (whichCache < 0 || + mtype.parameterSlotCount() > MethodType.MAX_MH_INVOKER_ARITY); + LambdaForm form; + if (!customized) { + form = mtype.form().cachedLambdaForm(whichCache); + if (form != null) return form; + } + final int THIS_DMH = 0; + final int ARG_BASE = 1; + final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); + int nameCursor = ARG_LIMIT; + final int NEXT_MH = customized ? -1 : nameCursor++; + final int REINVOKE = nameCursor++; + LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType()); + assert(names.length == nameCursor); + names[THIS_DMH] = names[THIS_DMH].withConstraint(constraint); + Object[] targetArgs; + if (customized) { + targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class); + names[REINVOKE] = new LambdaForm.Name(target, targetArgs); // the invoker is the target itself + } else { + names[NEXT_MH] = new LambdaForm.Name(getTargetFn, names[THIS_DMH]); + targetArgs = Arrays.copyOfRange(names, THIS_DMH, ARG_LIMIT, Object[].class); + targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH + names[REINVOKE] = new LambdaForm.Name(mtype, targetArgs); + } + String debugString; + switch(whichCache) { + case MethodTypeForm.LF_REBIND: debugString = "BMH.reinvoke"; break; + case MethodTypeForm.LF_DELEGATE: debugString = "MH.delegate"; break; + default: debugString = "MH.reinvoke"; break; + } + form = new LambdaForm(debugString, ARG_LIMIT, names); + if (!customized) { + form = mtype.form().setCachedLambdaForm(whichCache, form); + } + return form; + } + + private static final NamedFunction NF_getTarget; + static { + try { + NF_getTarget = new NamedFunction(DelegatingMethodHandle.class + .getDeclaredMethod("getTarget")); + } catch (ReflectiveOperationException ex) { + throw newInternalError(ex); + } + } +} diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java index 0fbc4619e22..e9d2526cd8d 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -59,6 +59,7 @@ class DirectMethodHandle extends MethodHandle { MemberName m = new MemberName(Object.class, member.getName(), member.getMethodType(), member.getReferenceKind()); m = MemberName.getFactory().resolveOrNull(m.getReferenceKind(), m, null); if (m != null && m.isPublic()) { + assert(member.getReferenceKind() == m.getReferenceKind()); // else this.form is wrong member = m; } } @@ -125,61 +126,31 @@ class DirectMethodHandle extends MethodHandle { return new Constructor(mtype, lform, ctor, init, instanceClass); } + @Override + BoundMethodHandle rebind() { + return BoundMethodHandle.makeReinvoker(this); + } + + @Override + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + assert(this.getClass() == DirectMethodHandle.class); // must override in subclasses + return new DirectMethodHandle(mt, lf, member); + } + @Override String internalProperties() { - return "/DMH="+member.toString(); + return "\n& DMH.MN="+internalMemberName(); } //// Implementation methods. @Override - MethodHandle viewAsType(MethodType newType) { - return new DirectMethodHandle(newType, form, member); - } - @Override @ForceInline MemberName internalMemberName() { return member; } - @Override - MethodHandle bindArgument(int pos, BasicType basicType, Object value) { - // If the member needs dispatching, do so. - if (pos == 0 && basicType == L_TYPE) { - DirectMethodHandle concrete = maybeRebind(value); - if (concrete != null) - return concrete.bindReceiver(value); - } - return super.bindArgument(pos, basicType, value); - } - - @Override - MethodHandle bindReceiver(Object receiver) { - // If the member needs dispatching, do so. - DirectMethodHandle concrete = maybeRebind(receiver); - if (concrete != null) - return concrete.bindReceiver(receiver); - return super.bindReceiver(receiver); - } - private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(); - private DirectMethodHandle maybeRebind(Object receiver) { - if (receiver != null) { - switch (member.getReferenceKind()) { - case REF_invokeInterface: - case REF_invokeVirtual: - // Pre-dispatch the member. - Class concreteClass = receiver.getClass(); - MemberName concrete = new MemberName(concreteClass, member.getName(), member.getMethodType(), REF_invokeSpecial); - concrete = IMPL_NAMES.resolveOrNull(REF_invokeSpecial, concrete, concreteClass); - if (concrete != null) - return new DirectMethodHandle(type(), preparedLambdaForm(concrete), concrete); - break; - } - } - return null; - } - /** * Create a LF which can invoke the given method. * Cache and share this structure among all methods with @@ -260,9 +231,10 @@ class DirectMethodHandle extends MethodHandle { } else { names[GET_MEMBER] = new Name(Lazy.NF_internalMemberName, names[DMH_THIS]); } + assert(findDirectMethodHandle(names[GET_MEMBER]) == names[DMH_THIS]); Object[] outArgs = Arrays.copyOfRange(names, ARG_BASE, GET_MEMBER+1, Object[].class); assert(outArgs[outArgs.length-1] == names[GET_MEMBER]); // look, shifted args! - int result = LambdaForm.LAST_RESULT; + int result = LAST_RESULT; if (doesAlloc) { assert(outArgs[outArgs.length-2] == names[NEW_OBJ]); // got to move this one System.arraycopy(outArgs, 0, outArgs, 1, outArgs.length-2); @@ -277,6 +249,16 @@ class DirectMethodHandle extends MethodHandle { return lform; } + static Object findDirectMethodHandle(Name name) { + if (name.function == Lazy.NF_internalMemberName || + name.function == Lazy.NF_internalMemberNameEnsureInit || + name.function == Lazy.NF_constructorMethod) { + assert(name.arguments.length == 1); + return name.arguments[0]; + } + return null; + } + private static void maybeCompile(LambdaForm lform, MemberName m) { if (VerifyAccess.isSamePackage(m.getDeclaringClass(), MethodHandle.class)) // Help along bootstrapping... @@ -389,8 +371,8 @@ class DirectMethodHandle extends MethodHandle { return true; } @Override - MethodHandle viewAsType(MethodType newType) { - return new Special(newType, form, member); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Special(mt, lf, member); } } @@ -407,8 +389,8 @@ class DirectMethodHandle extends MethodHandle { assert(initMethod.isResolved()); } @Override - MethodHandle viewAsType(MethodType newType) { - return new Constructor(newType, form, member, initMethod, instanceClass); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Constructor(mt, lf, member, initMethod, instanceClass); } } @@ -437,8 +419,8 @@ class DirectMethodHandle extends MethodHandle { return fieldType.cast(obj); } @Override - MethodHandle viewAsType(MethodType newType) { - return new Accessor(newType, form, member, fieldOffset); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new Accessor(mt, lf, member, fieldOffset); } } @@ -480,8 +462,8 @@ class DirectMethodHandle extends MethodHandle { return fieldType.cast(obj); } @Override - MethodHandle viewAsType(MethodType newType) { - return new StaticAccessor(newType, form, member, staticBase, staticOffset); + MethodHandle copyWith(MethodType mt, LambdaForm lf) { + return new StaticAccessor(mt, lf, member, staticBase, staticOffset); } } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java index 752c0976d9e..9d8db4eef78 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java @@ -98,7 +98,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*; private final String implMethodClassName; // Name of type containing implementation "CC" private final String implMethodName; // Name of implementation method "impl" private final String implMethodDesc; // Type descriptor for implementation methods "(I)Ljava/lang/String;" - private final Class implMethodReturnClass; // class for implementaion method return type "Ljava/lang/String;" + private final Class implMethodReturnClass; // class for implementation method return type "Ljava/lang/String;" private final MethodType constructorType; // Generated class constructor type "(CC)void" private final ClassWriter cw; // ASM class writer private final String[] argNames; // Generated names for the constructor arguments diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 3ab5d9c4dcf..0bfa6e32a98 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -25,21 +25,20 @@ package java.lang.invoke; -import sun.invoke.util.VerifyAccess; -import static java.lang.invoke.LambdaForm.*; - -import sun.invoke.util.Wrapper; - import java.io.*; import java.util.*; +import java.lang.reflect.Modifier; import jdk.internal.org.objectweb.asm.*; -import java.lang.reflect.*; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; -import static java.lang.invoke.LambdaForm.BasicType.*; + +import sun.invoke.util.VerifyAccess; import sun.invoke.util.VerifyType; +import sun.invoke.util.Wrapper; import sun.reflect.misc.ReflectUtil; /** @@ -74,7 +73,11 @@ class InvokerBytecodeGenerator { private final LambdaForm lambdaForm; private final String invokerName; private final MethodType invokerType; - private final int[] localsMap; + + /** Info about local variables in compiled lambda form */ + private final int[] localsMap; // index + private final BasicType[] localTypes; // basic type + private final Class[] localClasses; // type /** ASM bytecode generation. */ private ClassWriter cw; @@ -83,6 +86,7 @@ class InvokerBytecodeGenerator { private static final MemberName.Factory MEMBERNAME_FACTORY = MemberName.getFactory(); private static final Class HOST_CLASS = LambdaForm.class; + /** Main constructor; other constructors delegate to this one. */ private InvokerBytecodeGenerator(LambdaForm lambdaForm, int localsMapSize, String className, String invokerName, MethodType invokerType) { if (invokerName.contains(".")) { @@ -98,18 +102,26 @@ class InvokerBytecodeGenerator { this.lambdaForm = lambdaForm; this.invokerName = invokerName; this.invokerType = invokerType; - this.localsMap = new int[localsMapSize]; + this.localsMap = new int[localsMapSize+1]; + // last entry of localsMap is count of allocated local slots + this.localTypes = new BasicType[localsMapSize+1]; + this.localClasses = new Class[localsMapSize+1]; } + /** For generating LambdaForm interpreter entry points. */ private InvokerBytecodeGenerator(String className, String invokerName, MethodType invokerType) { this(null, invokerType.parameterCount(), className, invokerName, invokerType); // Create an array to map name indexes to locals indexes. + localTypes[localTypes.length - 1] = V_TYPE; for (int i = 0; i < localsMap.length; i++) { localsMap[i] = invokerType.parameterSlotCount() - invokerType.parameterSlotDepth(i); + if (i < invokerType.parameterCount()) + localTypes[i] = basicType(invokerType.parameterType(i)); } } + /** For generating customized code for a single LambdaForm. */ private InvokerBytecodeGenerator(String className, LambdaForm form, MethodType invokerType) { this(form, form.names.length, className, form.debugName, invokerType); @@ -117,7 +129,11 @@ class InvokerBytecodeGenerator { Name[] names = form.names; for (int i = 0, index = 0; i < localsMap.length; i++) { localsMap[i] = index; - index += names[i].type.basicTypeSlots(); + if (i < names.length) { + BasicType type = names[i].type(); + index += type.basicTypeSlots(); + localTypes[i] = type; + } } } @@ -148,7 +164,6 @@ class InvokerBytecodeGenerator { static void maybeDump(final String className, final byte[] classFile) { if (DUMP_CLASS_FILES) { - System.out.println("dump: " + className); java.security.AccessController.doPrivileged( new java.security.PrivilegedAction() { public Void run() { @@ -156,6 +171,7 @@ class InvokerBytecodeGenerator { String dumpName = className; //dumpName = dumpName.replace('/', '-'); File dumpFile = new File(DUMP_CLASS_FILES_DIR, dumpName+".class"); + System.out.println("dump: " + dumpFile); dumpFile.getParentFile().mkdirs(); FileOutputStream file = new FileOutputStream(dumpFile); file.write(classFile); @@ -204,12 +220,12 @@ class InvokerBytecodeGenerator { String constantPlaceholder(Object arg) { String cpPlaceholder = "CONSTANT_PLACEHOLDER_" + cph++; - if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + arg.toString() + ">>"; // debugging aid + if (DUMP_CLASS_FILES) cpPlaceholder += " <<" + debugString(arg) + ">>"; // debugging aid if (cpPatches.containsKey(cpPlaceholder)) { throw new InternalError("observed CP placeholder twice: " + cpPlaceholder); } // insert placeholder in CP and remember the patch - int index = cw.newConst((Object) cpPlaceholder); // TODO check if aready in the constant pool + int index = cw.newConst((Object) cpPlaceholder); // TODO check if already in the constant pool cpPatches.put(cpPlaceholder, new CpPatch(index, cpPlaceholder, arg)); return cpPlaceholder; } @@ -225,6 +241,17 @@ class InvokerBytecodeGenerator { return res; } + private static String debugString(Object arg) { + if (arg instanceof MethodHandle) { + MethodHandle mh = (MethodHandle) arg; + MemberName member = mh.internalMemberName(); + if (member != null) + return member.toString(); + return mh.debugString(); + } + return arg.toString(); + } + /** * Extract the number of constant pool entries from a given class file. * @@ -400,6 +427,64 @@ class InvokerBytecodeGenerator { emitStoreInsn(L_TYPE, index); } + private byte arrayTypeCode(Wrapper elementType) { + switch (elementType) { + case BOOLEAN: return Opcodes.T_BOOLEAN; + case BYTE: return Opcodes.T_BYTE; + case CHAR: return Opcodes.T_CHAR; + case SHORT: return Opcodes.T_SHORT; + case INT: return Opcodes.T_INT; + case LONG: return Opcodes.T_LONG; + case FLOAT: return Opcodes.T_FLOAT; + case DOUBLE: return Opcodes.T_DOUBLE; + case OBJECT: return 0; // in place of Opcodes.T_OBJECT + default: throw new InternalError(); + } + } + + private int arrayInsnOpcode(byte tcode, int aaop) throws InternalError { + assert(aaop == Opcodes.AASTORE || aaop == Opcodes.AALOAD); + int xas; + switch (tcode) { + case Opcodes.T_BOOLEAN: xas = Opcodes.BASTORE; break; + case Opcodes.T_BYTE: xas = Opcodes.BASTORE; break; + case Opcodes.T_CHAR: xas = Opcodes.CASTORE; break; + case Opcodes.T_SHORT: xas = Opcodes.SASTORE; break; + case Opcodes.T_INT: xas = Opcodes.IASTORE; break; + case Opcodes.T_LONG: xas = Opcodes.LASTORE; break; + case Opcodes.T_FLOAT: xas = Opcodes.FASTORE; break; + case Opcodes.T_DOUBLE: xas = Opcodes.DASTORE; break; + case 0: xas = Opcodes.AASTORE; break; + default: throw new InternalError(); + } + return xas - Opcodes.AASTORE + aaop; + } + + + private void freeFrameLocal(int oldFrameLocal) { + int i = indexForFrameLocal(oldFrameLocal); + if (i < 0) return; + BasicType type = localTypes[i]; + int newFrameLocal = makeLocalTemp(type); + mv.visitVarInsn(loadInsnOpcode(type), oldFrameLocal); + mv.visitVarInsn(storeInsnOpcode(type), newFrameLocal); + assert(localsMap[i] == oldFrameLocal); + localsMap[i] = newFrameLocal; + assert(indexForFrameLocal(oldFrameLocal) < 0); + } + private int indexForFrameLocal(int frameLocal) { + for (int i = 0; i < localsMap.length; i++) { + if (localsMap[i] == frameLocal && localTypes[i] != V_TYPE) + return i; + } + return -1; + } + private int makeLocalTemp(BasicType type) { + int frameLocal = localsMap[localsMap.length - 1]; + localsMap[localsMap.length - 1] = frameLocal + type.basicTypeSlots(); + return frameLocal; + } + /** * Emit a boxing call. * @@ -421,41 +506,79 @@ class InvokerBytecodeGenerator { String owner = "java/lang/" + wrapper.wrapperType().getSimpleName(); String name = wrapper.primitiveSimpleName() + "Value"; String desc = "()" + wrapper.basicTypeChar(); - mv.visitTypeInsn(Opcodes.CHECKCAST, owner); + emitReferenceCast(wrapper.wrapperType(), null); mv.visitMethodInsn(Opcodes.INVOKEVIRTUAL, owner, name, desc, false); } /** - * Emit an implicit conversion. + * Emit an implicit conversion for an argument which must be of the given pclass. + * This is usually a no-op, except when pclass is a subword type or a reference other than Object or an interface. * * @param ptype type of value present on stack * @param pclass type of value required on stack + * @param arg compile-time representation of value on stack (Node, constant) or null if none */ - private void emitImplicitConversion(BasicType ptype, Class pclass) { + private void emitImplicitConversion(BasicType ptype, Class pclass, Object arg) { assert(basicType(pclass) == ptype); // boxing/unboxing handled by caller if (pclass == ptype.basicTypeClass() && ptype != L_TYPE) return; // nothing to do switch (ptype) { - case L_TYPE: - if (VerifyType.isNullConversion(Object.class, pclass)) + case L_TYPE: + if (VerifyType.isNullConversion(Object.class, pclass, false)) { + if (PROFILE_LEVEL > 0) + emitReferenceCast(Object.class, arg); + return; + } + emitReferenceCast(pclass, arg); + return; + case I_TYPE: + if (!VerifyType.isNullConversion(int.class, pclass, false)) + emitPrimCast(ptype.basicTypeWrapper(), Wrapper.forPrimitiveType(pclass)); return; - if (isStaticallyNameable(pclass)) { - mv.visitTypeInsn(Opcodes.CHECKCAST, getInternalName(pclass)); - } else { - mv.visitLdcInsn(constantPlaceholder(pclass)); - mv.visitTypeInsn(Opcodes.CHECKCAST, CLS); - mv.visitInsn(Opcodes.SWAP); - mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG, false); - if (pclass.isArray()) - mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); - } - return; - case I_TYPE: - if (!VerifyType.isNullConversion(int.class, pclass)) - emitPrimCast(ptype.basicTypeWrapper(), Wrapper.forPrimitiveType(pclass)); - return; } - throw new InternalError("bad implicit conversion: tc="+ptype+": "+pclass); + throw newInternalError("bad implicit conversion: tc="+ptype+": "+pclass); + } + + /** Update localClasses type map. Return true if the information is already present. */ + private boolean assertStaticType(Class cls, Name n) { + int local = n.index(); + Class aclass = localClasses[local]; + if (aclass != null && (aclass == cls || cls.isAssignableFrom(aclass))) { + return true; // type info is already present + } else if (aclass == null || aclass.isAssignableFrom(cls)) { + localClasses[local] = cls; // type info can be improved + } + return false; + } + + private void emitReferenceCast(Class cls, Object arg) { + Name writeBack = null; // local to write back result + if (arg instanceof Name) { + Name n = (Name) arg; + if (assertStaticType(cls, n)) + return; // this cast was already performed + if (lambdaForm.useCount(n) > 1) { + // This guy gets used more than once. + writeBack = n; + } + } + if (isStaticallyNameable(cls)) { + String sig = getInternalName(cls); + mv.visitTypeInsn(Opcodes.CHECKCAST, sig); + } else { + mv.visitLdcInsn(constantPlaceholder(cls)); + mv.visitTypeInsn(Opcodes.CHECKCAST, CLS); + mv.visitInsn(Opcodes.SWAP); + mv.visitMethodInsn(Opcodes.INVOKESTATIC, MHI, "castReference", CLL_SIG, false); + if (Object[].class.isAssignableFrom(cls)) + mv.visitTypeInsn(Opcodes.CHECKCAST, OBJARY); + else if (PROFILE_LEVEL > 0) + mv.visitTypeInsn(Opcodes.CHECKCAST, OBJ); + } + if (writeBack != null) { + mv.visitInsn(Opcodes.DUP); + emitAstoreInsn(writeBack.index()); + } } /** @@ -477,7 +600,11 @@ class InvokerBytecodeGenerator { } private static String getInternalName(Class c) { - assert(VerifyAccess.isTypeVisible(c, Object.class)); + if (c == Object.class) return OBJ; + else if (c == Object[].class) return OBJARY; + else if (c == Class.class) return CLS; + else if (c == MethodHandle.class) return MH; + assert(VerifyAccess.isTypeVisible(c, Object.class)) : c.getName(); return c.getName().replace('.', '/'); } @@ -506,39 +633,62 @@ class InvokerBytecodeGenerator { // iterate over the form's names, generating bytecode instructions for each // start iterating at the first name following the arguments + Name onStack = null; for (int i = lambdaForm.arity; i < lambdaForm.names.length; i++) { Name name = lambdaForm.names[i]; - MemberName member = name.function.member(); - if (isSelectAlternative(i)) { - emitSelectAlternative(name, lambdaForm.names[i + 1]); - i++; // skip MH.invokeBasic of the selectAlternative result - } else if (isGuardWithCatch(i)) { - emitGuardWithCatch(i); - i = i+2; // Jump to the end of GWC idiom - } else if (isStaticallyInvocable(member)) { + emitStoreResult(onStack); + onStack = name; // unless otherwise modified below + MethodHandleImpl.Intrinsic intr = name.function.intrinsicName(); + switch (intr) { + case SELECT_ALTERNATIVE: + assert isSelectAlternative(i); + onStack = emitSelectAlternative(name, lambdaForm.names[i+1]); + i++; // skip MH.invokeBasic of the selectAlternative result + continue; + case GUARD_WITH_CATCH: + assert isGuardWithCatch(i); + onStack = emitGuardWithCatch(i); + i = i+2; // Jump to the end of GWC idiom + continue; + case NEW_ARRAY: + Class rtype = name.function.methodType().returnType(); + if (isStaticallyNameable(rtype)) { + emitNewArray(name); + continue; + } + break; + case ARRAY_LOAD: + emitArrayLoad(name); + continue; + case ARRAY_STORE: + emitArrayStore(name); + continue; + case IDENTITY: + assert(name.arguments.length == 1); + emitPushArguments(name); + continue; + case ZERO: + assert(name.arguments.length == 0); + emitConst(name.type.basicTypeWrapper().zero()); + continue; + case NONE: + // no intrinsic associated + break; + default: + throw newInternalError("Unknown intrinsic: "+intr); + } + + MemberName member = name.function.member(); + if (isStaticallyInvocable(member)) { emitStaticInvoke(member, name); } else { emitInvoke(name); } - - // Update cached form name's info in case an intrinsic spanning multiple names was encountered. - name = lambdaForm.names[i]; - member = name.function.member(); - - // store the result from evaluating to the target name in a local if required - // (if this is the last value, i.e., the one that is going to be returned, - // avoid store/load/return and just return) - if (i == lambdaForm.names.length - 1 && i == lambdaForm.result) { - // return value - do nothing - } else if (name.type != V_TYPE) { - // non-void: actually assign - emitStoreInsn(name.type, name.index()); - } } // return statement - emitReturn(); + emitReturn(onStack); classFileEpilogue(); bogusMethod(lambdaForm); @@ -548,29 +698,43 @@ class InvokerBytecodeGenerator { return classFile; } + void emitArrayLoad(Name name) { emitArrayOp(name, Opcodes.AALOAD); } + void emitArrayStore(Name name) { emitArrayOp(name, Opcodes.AASTORE); } + + void emitArrayOp(Name name, int arrayOpcode) { + assert arrayOpcode == Opcodes.AALOAD || arrayOpcode == Opcodes.AASTORE; + Class elementType = name.function.methodType().parameterType(0).getComponentType(); + assert elementType != null; + emitPushArguments(name); + if (elementType.isPrimitive()) { + Wrapper w = Wrapper.forPrimitiveType(elementType); + arrayOpcode = arrayInsnOpcode(arrayTypeCode(w), arrayOpcode); + } + mv.visitInsn(arrayOpcode); + } + /** * Emit an invoke for the given name. */ void emitInvoke(Name name) { + assert(!isLinkerMethodInvoke(name)); // should use the static path for these if (true) { // push receiver MethodHandle target = name.function.resolvedHandle; assert(target != null) : name.exprString(); mv.visitLdcInsn(constantPlaceholder(target)); - mv.visitTypeInsn(Opcodes.CHECKCAST, MH); + emitReferenceCast(MethodHandle.class, target); } else { // load receiver emitAloadInsn(0); - mv.visitTypeInsn(Opcodes.CHECKCAST, MH); + emitReferenceCast(MethodHandle.class, null); mv.visitFieldInsn(Opcodes.GETFIELD, MH, "form", LF_SIG); mv.visitFieldInsn(Opcodes.GETFIELD, LF, "names", LFN_SIG); // TODO more to come } // push arguments - for (int i = 0; i < name.arguments.length; i++) { - emitPushArgument(name, i); - } + emitPushArguments(name); // invocation MethodType type = name.function.methodType(); @@ -585,6 +749,10 @@ class InvokerBytecodeGenerator { //MethodHandle.class already covered }; + static boolean isStaticallyInvocable(Name name) { + return isStaticallyInvocable(name.function.member()); + } + static boolean isStaticallyInvocable(MemberName member) { if (member == null) return false; if (member.isConstructor()) return false; @@ -611,6 +779,8 @@ class InvokerBytecodeGenerator { } static boolean isStaticallyNameable(Class cls) { + if (cls == Object.class) + return true; while (cls.isArray()) cls = cls.getComponentType(); if (cls.isPrimitive()) @@ -631,12 +801,17 @@ class InvokerBytecodeGenerator { return false; } + void emitStaticInvoke(Name name) { + emitStaticInvoke(name.function.member(), name); + } + /** * Emit an invoke for the given name, using the MemberName directly. */ void emitStaticInvoke(MemberName member, Name name) { assert(member.equals(name.function.member())); - String cname = getInternalName(member.getDeclaringClass()); + Class defc = member.getDeclaringClass(); + String cname = getInternalName(defc); String mname = member.getName(); String mtype; byte refKind = member.getReferenceKind(); @@ -653,9 +828,7 @@ class InvokerBytecodeGenerator { } // push arguments - for (int i = 0; i < name.arguments.length; i++) { - emitPushArgument(name, i); - } + emitPushArguments(name); // invocation if (member.isMethod()) { @@ -666,6 +839,52 @@ class InvokerBytecodeGenerator { mtype = MethodType.toFieldDescriptorString(member.getFieldType()); mv.visitFieldInsn(refKindOpcode(refKind), cname, mname, mtype); } + // Issue a type assertion for the result, so we can avoid casts later. + if (name.type == L_TYPE) { + Class rtype = member.getInvocationType().returnType(); + assert(!rtype.isPrimitive()); + if (rtype != Object.class && !rtype.isInterface()) { + assertStaticType(rtype, name); + } + } + } + + void emitNewArray(Name name) throws InternalError { + Class rtype = name.function.methodType().returnType(); + if (name.arguments.length == 0) { + // The array will be a constant. + Object emptyArray; + try { + emptyArray = name.function.resolvedHandle.invoke(); + } catch (Throwable ex) { + throw newInternalError(ex); + } + assert(java.lang.reflect.Array.getLength(emptyArray) == 0); + assert(emptyArray.getClass() == rtype); // exact typing + mv.visitLdcInsn(constantPlaceholder(emptyArray)); + emitReferenceCast(rtype, emptyArray); + return; + } + Class arrayElementType = rtype.getComponentType(); + assert(arrayElementType != null); + emitIconstInsn(name.arguments.length); + int xas = Opcodes.AASTORE; + if (!arrayElementType.isPrimitive()) { + mv.visitTypeInsn(Opcodes.ANEWARRAY, getInternalName(arrayElementType)); + } else { + byte tc = arrayTypeCode(Wrapper.forPrimitiveType(arrayElementType)); + xas = arrayInsnOpcode(tc, xas); + mv.visitIntInsn(Opcodes.NEWARRAY, tc); + } + // store arguments + for (int i = 0; i < name.arguments.length; i++) { + mv.visitInsn(Opcodes.DUP); + emitIconstInsn(i); + emitPushArgument(name, i); + mv.visitInsn(xas); + } + // the array is left on the stack + assertStaticType(rtype, name); } int refKindOpcode(byte refKind) { switch (refKind) { @@ -707,6 +926,21 @@ class InvokerBytecodeGenerator { !member.isPublic() && !member.isStatic(); } + /** + * Check if MemberName is a call to MethodHandle.linkToStatic, etc. + */ + private boolean isLinkerMethodInvoke(Name name) { + if (name.function == null) + return false; + if (name.arguments.length < 1) + return false; // must have MH argument + MemberName member = name.function.member(); + return member != null && + member.getDeclaringClass() == MethodHandle.class && + !member.isPublic() && member.isStatic() && + member.getName().startsWith("linkTo"); + } + /** * Check if i-th name is a call to MethodHandleImpl.selectAlternative. */ @@ -755,7 +989,9 @@ class InvokerBytecodeGenerator { * t4:I=MethodHandle.invokeBasic(t3:L,a1:I);t4:I} * }
    */ - private void emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { + private Name emitSelectAlternative(Name selectAlternativeName, Name invokeBasicName) { + assert isStaticallyInvocable(invokeBasicName); + Name receiver = (Name) invokeBasicName.arguments[0]; Label L_fallback = new Label(); @@ -763,15 +999,15 @@ class InvokerBytecodeGenerator { // load test result emitPushArgument(selectAlternativeName, 0); - mv.visitInsn(Opcodes.ICONST_1); // if_icmpne L_fallback - mv.visitJumpInsn(Opcodes.IF_ICMPNE, L_fallback); + mv.visitJumpInsn(Opcodes.IFEQ, L_fallback); // invoke selectAlternativeName.arguments[1] + Class[] preForkClasses = localClasses.clone(); emitPushArgument(selectAlternativeName, 1); // get 2nd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot - emitInvoke(invokeBasicName); + emitStaticInvoke(invokeBasicName); // goto L_done mv.visitJumpInsn(Opcodes.GOTO, L_done); @@ -780,12 +1016,17 @@ class InvokerBytecodeGenerator { mv.visitLabel(L_fallback); // invoke selectAlternativeName.arguments[2] + System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); emitPushArgument(selectAlternativeName, 2); // get 3rd argument of selectAlternative emitAstoreInsn(receiver.index()); // store the MH in the receiver slot - emitInvoke(invokeBasicName); + emitStaticInvoke(invokeBasicName); // L_done: mv.visitLabel(L_done); + // for now do not bother to merge typestate; just reset to the dominator state + System.arraycopy(preForkClasses, 0, localClasses, 0, preForkClasses.length); + + return invokeBasicName; // return what's on stack } /** @@ -808,7 +1049,7 @@ class InvokerBytecodeGenerator { * return a3.invokeBasic(ex, a6, a7); * }} */ - private void emitGuardWithCatch(int pos) { + private Name emitGuardWithCatch(int pos) { Name args = lambdaForm.names[pos]; Name invoker = lambdaForm.names[pos+1]; Name result = lambdaForm.names[pos+2]; @@ -859,6 +1100,12 @@ class InvokerBytecodeGenerator { mv.visitInsn(Opcodes.ATHROW); mv.visitLabel(L_done); + + return result; + } + + private void emitPushArguments(Name args) { + emitPushArguments(args, 0); } private void emitPushArguments(Name args, int start) { @@ -878,7 +1125,7 @@ class InvokerBytecodeGenerator { if (arg instanceof Name) { Name n = (Name) arg; emitLoadInsn(n.type, n.index()); - emitImplicitConversion(n.type, ptype); + emitImplicitConversion(n.type, ptype, n); } else if ((arg == null || arg instanceof String) && bptype == L_TYPE) { emitConst(arg); } else { @@ -886,15 +1133,25 @@ class InvokerBytecodeGenerator { emitConst(arg); } else { mv.visitLdcInsn(constantPlaceholder(arg)); - emitImplicitConversion(L_TYPE, ptype); + emitImplicitConversion(L_TYPE, ptype, arg); } } } + /** + * Store the name to its local, if necessary. + */ + private void emitStoreResult(Name name) { + if (name != null && name.type != V_TYPE) { + // non-void: actually assign + emitStoreInsn(name.type, name.index()); + } + } + /** * Emits a return statement from a LF invoker. If required, the result type is cast to the correct return type. */ - private void emitReturn() { + private void emitReturn(Name onStack) { // return statement Class rclass = invokerType.returnType(); BasicType rtype = lambdaForm.returnType(); @@ -907,12 +1164,11 @@ class InvokerBytecodeGenerator { LambdaForm.Name rn = lambdaForm.names[lambdaForm.result]; // put return value on the stack if it is not already there - if (lambdaForm.result != lambdaForm.names.length - 1 || - lambdaForm.result < lambdaForm.arity) { - emitLoadInsn(rn.type, lambdaForm.result); + if (rn != onStack) { + emitLoadInsn(rtype, lambdaForm.result); } - emitImplicitConversion(rtype, rclass); + emitImplicitConversion(rtype, rclass, rn); // generate actual return statement emitReturnInsn(rtype); diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java index b9c18b548bd..12a118a7576 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/Invokers.java @@ -25,8 +25,9 @@ package java.lang.invoke; +import java.lang.reflect.Array; import java.util.Arrays; -import sun.invoke.empty.Empty; + import static java.lang.invoke.MethodHandleStatics.*; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; @@ -37,55 +38,66 @@ import static java.lang.invoke.LambdaForm.*; * @author jrose */ class Invokers { - // exact type (sans leading taget MH) for the outgoing call + // exact type (sans leading target MH) for the outgoing call private final MethodType targetType; - // FIXME: Get rid of the invokers that are not useful. - - // exact invoker for the outgoing call - private /*lazy*/ MethodHandle exactInvoker; - private /*lazy*/ MethodHandle basicInvoker; // invokeBasic (unchecked exact) - - // erased (partially untyped but with primitives) invoker for the outgoing call - // FIXME: get rid of - private /*lazy*/ MethodHandle erasedInvoker; - // FIXME: get rid of - /*lazy*/ MethodHandle erasedInvokerWithDrops; // for InvokeGeneric - - // general invoker for the outgoing call - private /*lazy*/ MethodHandle generalInvoker; - - // general invoker for the outgoing call, uses varargs - private /*lazy*/ MethodHandle varargsInvoker; - - // general invoker for the outgoing call; accepts a trailing Object[] - private final /*lazy*/ MethodHandle[] spreadInvokers; - - // invoker for an unbound callsite - private /*lazy*/ MethodHandle uninitializedCallSite; + // Cached adapter information: + private final @Stable MethodHandle[] invokers = new MethodHandle[INV_LIMIT]; + // Indexes into invokers: + static final int + INV_EXACT = 0, // MethodHandles.exactInvoker + INV_GENERIC = 1, // MethodHandles.invoker (generic invocation) + INV_BASIC = 2, // MethodHandles.basicInvoker + INV_LIMIT = 3; /** Compute and cache information common to all collecting adapters * that implement members of the erasure-family of the given erased type. */ /*non-public*/ Invokers(MethodType targetType) { this.targetType = targetType; - this.spreadInvokers = new MethodHandle[targetType.parameterCount()+1]; } /*non-public*/ MethodHandle exactInvoker() { - MethodHandle invoker = exactInvoker; + MethodHandle invoker = cachedInvoker(INV_EXACT); if (invoker != null) return invoker; invoker = makeExactOrGeneralInvoker(true); - exactInvoker = invoker; - return invoker; + return setCachedInvoker(INV_EXACT, invoker); } - /*non-public*/ MethodHandle generalInvoker() { - MethodHandle invoker = generalInvoker; + /*non-public*/ MethodHandle genericInvoker() { + MethodHandle invoker = cachedInvoker(INV_GENERIC); if (invoker != null) return invoker; invoker = makeExactOrGeneralInvoker(false); - generalInvoker = invoker; - return invoker; + return setCachedInvoker(INV_GENERIC, invoker); + } + + /*non-public*/ MethodHandle basicInvoker() { + MethodHandle invoker = cachedInvoker(INV_BASIC); + if (invoker != null) return invoker; + MethodType basicType = targetType.basicType(); + if (basicType != targetType) { + // double cache; not used significantly + return setCachedInvoker(INV_BASIC, basicType.invokers().basicInvoker()); + } + invoker = basicType.form().cachedMethodHandle(MethodTypeForm.MH_BASIC_INV); + if (invoker == null) { + MemberName method = invokeBasicMethod(basicType); + invoker = DirectMethodHandle.make(method); + assert(checkInvoker(invoker)); + invoker = basicType.form().setCachedMethodHandle(MethodTypeForm.MH_BASIC_INV, invoker); + } + return setCachedInvoker(INV_BASIC, invoker); + } + + private MethodHandle cachedInvoker(int idx) { + return invokers[idx]; + } + + private synchronized MethodHandle setCachedInvoker(int idx, final MethodHandle invoker) { + // Simulate a CAS, to avoid racy duplication of results. + MethodHandle prev = invokers[idx]; + if (prev != null) return prev; + return invokers[idx] = invoker; } private MethodHandle makeExactOrGeneralInvoker(boolean isExact) { @@ -95,7 +107,7 @@ class Invokers { LambdaForm lform = invokeHandleForm(mtype, false, which); MethodHandle invoker = BoundMethodHandle.bindSingle(invokerType, lform, mtype); String whichName = (isExact ? "invokeExact" : "invoke"); - invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype)); + invoker = invoker.withInternalMemberName(MemberName.makeMethodHandleInvoke(whichName, mtype), false); assert(checkInvoker(invoker)); maybeCompileToBytecode(invoker); return invoker; @@ -110,21 +122,6 @@ class Invokers { } } - /*non-public*/ MethodHandle basicInvoker() { - MethodHandle invoker = basicInvoker; - if (invoker != null) return invoker; - MethodType basicType = targetType.basicType(); - if (basicType != targetType) { - // double cache; not used significantly - return basicInvoker = basicType.invokers().basicInvoker(); - } - MemberName method = invokeBasicMethod(basicType); - invoker = DirectMethodHandle.make(method); - assert(checkInvoker(invoker)); - basicInvoker = invoker; - return invoker; - } - // This next one is called from LambdaForm.NamedFunction.. /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) { assert(basicType == basicType.basicType()); @@ -145,87 +142,42 @@ class Invokers { return true; } - // FIXME: get rid of - /*non-public*/ MethodHandle erasedInvoker() { - MethodHandle xinvoker = exactInvoker(); - MethodHandle invoker = erasedInvoker; - if (invoker != null) return invoker; - MethodType erasedType = targetType.erase(); - invoker = xinvoker.asType(erasedType.invokerType()); - erasedInvoker = invoker; - return invoker; - } - + /** + * Find or create an invoker which passes unchanged a given number of arguments + * and spreads the rest from a trailing array argument. + * The invoker target type is the post-spread type {@code (TYPEOF(uarg*), TYPEOF(sarg*))=>RT}. + * All the {@code sarg}s must have a common type {@code C}. (If there are none, {@code Object} is assumed.} + * @param leadingArgCount the number of unchanged (non-spread) arguments + * @return {@code invoker.invokeExact(mh, uarg*, C[]{sarg*}) := (RT)mh.invoke(uarg*, sarg*)} + */ /*non-public*/ MethodHandle spreadInvoker(int leadingArgCount) { - MethodHandle vaInvoker = spreadInvokers[leadingArgCount]; - if (vaInvoker != null) return vaInvoker; int spreadArgCount = targetType.parameterCount() - leadingArgCount; - MethodType spreadInvokerType = targetType - .replaceParameterTypes(leadingArgCount, targetType.parameterCount(), Object[].class); - if (targetType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) { - // Factor sinvoker.invoke(mh, a) into ginvoker.asSpreader().invoke(mh, a) - // where ginvoker.invoke(mh, a*) => mh.invoke(a*). - MethodHandle genInvoker = generalInvoker(); - vaInvoker = genInvoker.asSpreader(Object[].class, spreadArgCount); - } else { - // Cannot build a general invoker here of type ginvoker.invoke(mh, a*[254]). - // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a) - // where filter(mh) == mh.asSpreader(Object[], spreadArgCount) - MethodHandle arrayInvoker = MethodHandles.exactInvoker(spreadInvokerType); - MethodHandle makeSpreader; - try { - makeSpreader = IMPL_LOOKUP - .findVirtual(MethodHandle.class, "asSpreader", - MethodType.methodType(MethodHandle.class, Class.class, int.class)); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - makeSpreader = MethodHandles.insertArguments(makeSpreader, 1, Object[].class, spreadArgCount); - vaInvoker = MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader); + MethodType postSpreadType = targetType; + Class argArrayType = impliedRestargType(postSpreadType, leadingArgCount); + if (postSpreadType.parameterSlotCount() <= MethodType.MAX_MH_INVOKER_ARITY) { + return genericInvoker().asSpreader(argArrayType, spreadArgCount); } - assert(vaInvoker.type().equals(spreadInvokerType.invokerType())); - maybeCompileToBytecode(vaInvoker); - spreadInvokers[leadingArgCount] = vaInvoker; - return vaInvoker; + // Cannot build a generic invoker here of type ginvoker.invoke(mh, a*[254]). + // Instead, factor sinvoker.invoke(mh, a) into ainvoker.invoke(filter(mh), a) + // where filter(mh) == mh.asSpreader(Object[], spreadArgCount) + MethodType preSpreadType = postSpreadType + .replaceParameterTypes(leadingArgCount, postSpreadType.parameterCount(), argArrayType); + MethodHandle arrayInvoker = MethodHandles.invoker(preSpreadType); + MethodHandle makeSpreader = MethodHandles.insertArguments(Lazy.MH_asSpreader, 1, argArrayType, spreadArgCount); + return MethodHandles.filterArgument(arrayInvoker, 0, makeSpreader); } - /*non-public*/ MethodHandle varargsInvoker() { - MethodHandle vaInvoker = varargsInvoker; - if (vaInvoker != null) return vaInvoker; - vaInvoker = spreadInvoker(0).asType(MethodType.genericMethodType(0, true).invokerType()); - varargsInvoker = vaInvoker; - return vaInvoker; - } - - private static MethodHandle THROW_UCS = null; - - /*non-public*/ MethodHandle uninitializedCallSite() { - MethodHandle invoker = uninitializedCallSite; - if (invoker != null) return invoker; - if (targetType.parameterCount() > 0) { - MethodType type0 = targetType.dropParameterTypes(0, targetType.parameterCount()); - Invokers invokers0 = type0.invokers(); - invoker = MethodHandles.dropArguments(invokers0.uninitializedCallSite(), - 0, targetType.parameterList()); - assert(invoker.type().equals(targetType)); - uninitializedCallSite = invoker; - return invoker; + private static Class impliedRestargType(MethodType restargType, int fromPos) { + if (restargType.isGeneric()) return Object[].class; // can be nothing else + int maxPos = restargType.parameterCount(); + if (fromPos >= maxPos) return Object[].class; // reasonable default + Class argType = restargType.parameterType(fromPos); + for (int i = fromPos+1; i < maxPos; i++) { + if (argType != restargType.parameterType(i)) + throw newIllegalArgumentException("need homogeneous rest arguments", restargType); } - invoker = THROW_UCS; - if (invoker == null) { - try { - THROW_UCS = invoker = IMPL_LOOKUP - .findStatic(CallSite.class, "uninitializedCallSite", - MethodType.methodType(Empty.class)); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - } - invoker = MethodHandles.explicitCastArguments(invoker, MethodType.methodType(targetType.returnType())); - invoker = invoker.dropArguments(targetType, 0, targetType.parameterCount()); - assert(invoker.type().equals(targetType)); - uninitializedCallSite = invoker; - return invoker; + if (argType == Object.class) return Object[].class; + return Array.newInstance(argType, 0).getClass(); } public String toString() { @@ -308,7 +260,9 @@ class Invokers { : Arrays.asList(mtype, customized, which, nameCursor, names.length); if (MTYPE_ARG >= INARG_LIMIT) { assert(names[MTYPE_ARG] == null); - NamedFunction getter = BoundMethodHandle.getSpeciesData("L").getterFunction(0); + BoundMethodHandle.SpeciesData speciesData = BoundMethodHandle.speciesData_L(); + names[THIS_MH] = names[THIS_MH].withConstraint(speciesData); + NamedFunction getter = speciesData.getterFunction(0); names[MTYPE_ARG] = new Name(getter, names[THIS_MH]); // else if isLinker, then MTYPE is passed in from the caller (e.g., the JVM) } @@ -360,9 +314,6 @@ class Invokers { Object checkGenericType(Object mhObj, Object expectedObj) { MethodHandle mh = (MethodHandle) mhObj; MethodType expected = (MethodType) expectedObj; - if (mh.type() == expected) return mh; - MethodHandle atc = mh.asTypeCache; - if (atc != null && atc.type() == expected) return atc; return mh.asType(expected); /* Maybe add more paths here. Possible optimizations: * for (R)MH.invoke(a*), @@ -436,27 +387,40 @@ class Invokers { } // Local constant functions: - private static final NamedFunction NF_checkExactType; - private static final NamedFunction NF_checkGenericType; - private static final NamedFunction NF_asType; - private static final NamedFunction NF_getCallSiteTarget; + private static final NamedFunction + NF_checkExactType, + NF_checkGenericType, + NF_getCallSiteTarget; static { try { - NF_checkExactType = new NamedFunction(Invokers.class - .getDeclaredMethod("checkExactType", Object.class, Object.class)); - NF_checkGenericType = new NamedFunction(Invokers.class - .getDeclaredMethod("checkGenericType", Object.class, Object.class)); - NF_asType = new NamedFunction(MethodHandle.class - .getDeclaredMethod("asType", MethodType.class)); - NF_getCallSiteTarget = new NamedFunction(Invokers.class - .getDeclaredMethod("getCallSiteTarget", Object.class)); - NF_checkExactType.resolve(); - NF_checkGenericType.resolve(); - NF_getCallSiteTarget.resolve(); - // bound + NamedFunction nfs[] = { + NF_checkExactType = new NamedFunction(Invokers.class + .getDeclaredMethod("checkExactType", Object.class, Object.class)), + NF_checkGenericType = new NamedFunction(Invokers.class + .getDeclaredMethod("checkGenericType", Object.class, Object.class)), + NF_getCallSiteTarget = new NamedFunction(Invokers.class + .getDeclaredMethod("getCallSiteTarget", Object.class)) + }; + for (NamedFunction nf : nfs) { + // Each nf must be statically invocable or we get tied up in our bootstraps. + assert(InvokerBytecodeGenerator.isStaticallyInvocable(nf.member)) : nf; + nf.resolve(); + } } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } } + private static class Lazy { + private static final MethodHandle MH_asSpreader; + + static { + try { + MH_asSpreader = IMPL_LOOKUP.findVirtual(MethodHandle.class, "asSpreader", + MethodType.methodType(MethodHandle.class, Class.class, int.class)); + } catch (ReflectiveOperationException ex) { + throw newInternalError(ex); + } + } + } } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java index 0676b7b3ab0..b83040647c5 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaForm.java @@ -27,11 +27,10 @@ package java.lang.invoke; import java.lang.annotation.*; import java.lang.reflect.Method; -import java.util.Map; import java.util.List; import java.util.Arrays; import java.util.HashMap; -import java.util.concurrent.ConcurrentHashMap; + import sun.invoke.util.Wrapper; import java.lang.reflect.Field; @@ -125,8 +124,7 @@ class LambdaForm { MemberName vmentry; // low-level behavior, or null if not yet prepared private boolean isCompiled; - // Caches for common structural transforms: - LambdaForm[] bindCache; + Object transformCache; // managed by LambdaFormEditor public static final int VOID_RESULT = -1, LAST_RESULT = -2; @@ -214,6 +212,13 @@ class LambdaForm { } return btypes; } + static byte[] basicTypesOrd(BasicType[] btypes) { + byte[] ords = new byte[btypes.length]; + for (int i = 0; i < btypes.length; i++) { + ords[i] = (byte)btypes[i].ordinal(); + } + return ords; + } static boolean isBasicTypeChar(char c) { return "LIJFDV".indexOf(c) >= 0; } @@ -243,7 +248,12 @@ class LambdaForm { this.result = fixResult(result, names); this.names = names.clone(); this.debugName = fixDebugName(debugName); - normalize(); + int maxOutArity = normalize(); + if (maxOutArity > MethodType.MAX_MH_INVOKER_ARITY) { + // Cannot use LF interpreter on very high arity expressions. + assert(maxOutArity <= MethodType.MAX_JVM_ARITY); + compileToBytecode(); + } } LambdaForm(String debugName, @@ -348,9 +358,12 @@ class LambdaForm { return true; } - /** Renumber and/or replace params so that they are interned and canonically numbered. */ - private void normalize() { + /** Renumber and/or replace params so that they are interned and canonically numbered. + * @return maximum argument list length among the names (since we have to pass over them anyway) + */ + private int normalize() { Name[] oldNames = null; + int maxOutArity = 0; int changesStart = 0; for (int i = 0; i < names.length; i++) { Name n = names[i]; @@ -361,6 +374,8 @@ class LambdaForm { } names[i] = n.cloneWithIndex(i); } + if (n.arguments != null && maxOutArity < n.arguments.length) + maxOutArity = n.arguments.length; } if (oldNames != null) { int startFixing = arity; @@ -387,6 +402,7 @@ class LambdaForm { } assert(nameRefsAreLegal()); } + return maxOutArity; } /** @@ -398,7 +414,7 @@ class LambdaForm { * This allows Name references to be freely reused to construct * fresh lambdas, without confusion. */ - private boolean nameRefsAreLegal() { + boolean nameRefsAreLegal() { assert(arity >= 0 && arity <= names.length); assert(result >= -1 && result < names.length); // Do all names possess an index consistent with their local definition order? @@ -439,8 +455,20 @@ class LambdaForm { /** Report the N-th argument type. */ BasicType parameterType(int n) { + return parameter(n).type; + } + + /** Report the N-th argument name. */ + Name parameter(int n) { assert(n < arity); - return names[n].type; + Name param = names[n]; + assert(param.isParam()); + return param; + } + + /** Report the N-th argument type constraint. */ + Object parameterConstraint(int n) { + return parameter(n).constraint; } /** Report the arity. */ @@ -448,6 +476,11 @@ class LambdaForm { return arity; } + /** Report the number of expressions (non-parameter names). */ + int expressionCount() { + return names.length - arity; + } + /** Return the method type corresponding to my basic type signature. */ MethodType methodType() { return signatureType(basicTypeSignature()); @@ -464,7 +497,7 @@ class LambdaForm { return sig.indexOf('_'); } static BasicType signatureReturn(String sig) { - return basicType(sig.charAt(signatureArity(sig)+1)); + return basicType(sig.charAt(signatureArity(sig) + 1)); } static boolean isValidSignature(String sig) { int arity = sig.indexOf('_'); @@ -582,21 +615,12 @@ class LambdaForm { isCompiled = true; return vmentry; } catch (Error | Exception ex) { - throw newInternalError("compileToBytecode", ex); + throw newInternalError(this.toString(), ex); } } - private static final ConcurrentHashMap PREPARED_FORMS; - static { - int capacity = 512; // expect many distinct signatures over time - float loadFactor = 0.75f; // normal default - int writers = 1; - PREPARED_FORMS = new ConcurrentHashMap<>(capacity, loadFactor, writers); - } - - private static Map computeInitialPreparedForms() { + private static void computeInitialPreparedForms() { // Find all predefined invokers and associate them with canonical empty lambda forms. - HashMap forms = new HashMap<>(); for (MemberName m : MemberName.getFactory().getMethods(LambdaForm.class, false, null, null, null)) { if (!m.isStatic() || !m.isPackage()) continue; MethodType mt = m.getMethodType(); @@ -607,13 +631,9 @@ class LambdaForm { assert(m.getName().equals("interpret" + sig.substring(sig.indexOf('_')))); LambdaForm form = new LambdaForm(sig); form.vmentry = m; - form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_COUNTER, form); - // FIXME: get rid of PREPARED_FORMS; use MethodTypeForm cache only - forms.put(sig, form); + form = mt.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, form); } } - //System.out.println("computeInitialPreparedForms => "+forms); - return forms; } // Set this false to disable use of the interpret_L methods defined in this file. @@ -647,13 +667,11 @@ class LambdaForm { } private static LambdaForm getPreparedForm(String sig) { MethodType mtype = signatureType(sig); - //LambdaForm prep = PREPARED_FORMS.get(sig); LambdaForm prep = mtype.form().cachedLambdaForm(MethodTypeForm.LF_INTERPRET); if (prep != null) return prep; assert(isValidSignature(sig)); prep = new LambdaForm(sig); prep.vmentry = InvokerBytecodeGenerator.generateLambdaFormInterpreterEntryPoint(sig); - //LambdaForm prep2 = PREPARED_FORMS.putIfAbsent(sig.intern(), prep); return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_INTERPRET, prep); } @@ -709,10 +727,7 @@ class LambdaForm { /** If the invocation count hits the threshold we spin bytecodes and call that subsequently. */ private static final int COMPILE_THRESHOLD; static { - if (MethodHandleStatics.COMPILE_THRESHOLD != null) - COMPILE_THRESHOLD = MethodHandleStatics.COMPILE_THRESHOLD; - else - COMPILE_THRESHOLD = 30; // default value + COMPILE_THRESHOLD = Math.max(-1, MethodHandleStatics.COMPILE_THRESHOLD); } private int invocationCounter = 0; @@ -728,7 +743,9 @@ class LambdaForm { for (int i = argumentValues.length; i < values.length; i++) { values[i] = interpretName(names[i], values); } - return (result < 0) ? null : values[result]; + Object rv = (result < 0) ? null : values[result]; + assert(resultCheck(argumentValues, rv)); + return rv; } @Hidden @@ -785,28 +802,6 @@ class LambdaForm { return rval; } - //** This transform is applied (statically) to every name.function. */ - /* - private static MethodHandle eraseSubwordTypes(MethodHandle mh) { - MethodType mt = mh.type(); - if (mt.hasPrimitives()) { - mt = mt.changeReturnType(eraseSubwordType(mt.returnType())); - for (int i = 0; i < mt.parameterCount(); i++) { - mt = mt.changeParameterType(i, eraseSubwordType(mt.parameterType(i))); - } - mh = MethodHandles.explicitCastArguments(mh, mt); - } - return mh; - } - private static Class eraseSubwordType(Class type) { - if (!type.isPrimitive()) return type; - if (type == int.class) return type; - Wrapper w = Wrapper.forPrimitiveType(type); - if (w.isSubwordOrInt()) return int.class; - return type; - } - */ - static void traceInterpreter(String event, Object obj, Object... args) { if (TRACE_INTERPRETER) { System.out.println("LFI: "+event+" "+(obj != null ? obj : "")+(args != null && args.length != 0 ? Arrays.asList(args) : "")); @@ -819,8 +814,16 @@ class LambdaForm { assert(argumentValues.length == arity) : arity+"!="+Arrays.asList(argumentValues)+".length"; // also check that the leading (receiver) argument is somehow bound to this LF: assert(argumentValues[0] instanceof MethodHandle) : "not MH: " + argumentValues[0]; - assert(((MethodHandle)argumentValues[0]).internalForm() == this); + MethodHandle mh = (MethodHandle) argumentValues[0]; + assert(mh.internalForm() == this); // note: argument #0 could also be an interface wrapper, in the future + argumentTypesMatch(basicTypeSignature(), argumentValues); + return true; + } + private boolean resultCheck(Object[] argumentValues, Object result) { + MethodHandle mh = (MethodHandle) argumentValues[0]; + MethodType mt = mh.type(); + assert(valueMatches(returnType(), mt.returnType(), result)); return true; } @@ -839,7 +842,7 @@ class LambdaForm { if (i == arity) buf.append(")=>{"); Name n = names[i]; if (i >= arity) buf.append("\n "); - buf.append(n); + buf.append(n.paramString()); if (i < arity) { if (i+1 < arity) buf.append(","); continue; @@ -847,6 +850,7 @@ class LambdaForm { buf.append("=").append(n.exprString()); buf.append(";"); } + if (arity == names.length) buf.append(")=>{"); buf.append(result < 0 ? "void" : names[result]).append("}"); if (TRACE_INTERPRETER) { // Extra verbosity: @@ -856,135 +860,19 @@ class LambdaForm { return buf.toString(); } - /** - * Apply immediate binding for a Name in this form indicated by its position relative to the form. - * The first parameter to a LambdaForm, a0:L, always represents the form's method handle, so 0 is not - * accepted as valid. - */ - LambdaForm bindImmediate(int pos, BasicType basicType, Object value) { - // must be an argument, and the types must match - assert pos > 0 && pos < arity && names[pos].type == basicType && Name.typesMatch(basicType, value); - - int arity2 = arity - 1; - Name[] names2 = new Name[names.length - 1]; - for (int r = 0, w = 0; r < names.length; ++r, ++w) { // (r)ead from names, (w)rite to names2 - Name n = names[r]; - if (n.isParam()) { - if (n.index == pos) { - // do not copy over the argument that is to be replaced with a literal, - // but adjust the write index - --w; - } else { - names2[w] = new Name(w, n.type); - } - } else { - Object[] arguments2 = new Object[n.arguments.length]; - for (int i = 0; i < n.arguments.length; ++i) { - Object arg = n.arguments[i]; - if (arg instanceof Name) { - int ni = ((Name) arg).index; - if (ni == pos) { - arguments2[i] = value; - } else if (ni < pos) { - // replacement position not yet passed - arguments2[i] = names2[ni]; - } else { - // replacement position passed - arguments2[i] = names2[ni - 1]; - } - } else { - arguments2[i] = arg; - } - } - names2[w] = new Name(n.function, arguments2); - names2[w].initIndex(w); - } - } - - int result2 = result == -1 ? -1 : result - 1; - return new LambdaForm(debugName, arity2, names2, result2); + @Override + public boolean equals(Object obj) { + return obj instanceof LambdaForm && equals((LambdaForm)obj); } - - LambdaForm bind(int namePos, BoundMethodHandle.SpeciesData oldData) { - Name name = names[namePos]; - BoundMethodHandle.SpeciesData newData = oldData.extendWith(name.type); - return bind(name, new Name(newData.getterFunction(oldData.fieldCount()), names[0]), oldData, newData); + public boolean equals(LambdaForm that) { + if (this.result != that.result) return false; + return Arrays.equals(this.names, that.names); } - LambdaForm bind(Name name, Name binding, - BoundMethodHandle.SpeciesData oldData, - BoundMethodHandle.SpeciesData newData) { - int pos = name.index; - assert(name.isParam()); - assert(!binding.isParam()); - assert(name.type == binding.type); - assert(0 <= pos && pos < arity && names[pos] == name); - assert(binding.function.memberDeclaringClassOrNull() == newData.clazz); - assert(oldData.getters.length == newData.getters.length-1); - if (bindCache != null) { - LambdaForm form = bindCache[pos]; - if (form != null) { - assert(form.contains(binding)) : "form << " + form + " >> does not contain binding << " + binding + " >>"; - return form; - } - } else { - bindCache = new LambdaForm[arity]; - } - assert(nameRefsAreLegal()); - int arity2 = arity-1; - Name[] names2 = names.clone(); - names2[pos] = binding; // we might move this in a moment - - // The newly created LF will run with a different BMH. - // Switch over any pre-existing BMH field references to the new BMH class. - int firstOldRef = -1; - for (int i = 0; i < names2.length; i++) { - Name n = names[i]; - if (n.function != null && - n.function.memberDeclaringClassOrNull() == oldData.clazz) { - MethodHandle oldGetter = n.function.resolvedHandle; - MethodHandle newGetter = null; - for (int j = 0; j < oldData.getters.length; j++) { - if (oldGetter == oldData.getters[j]) - newGetter = newData.getters[j]; - } - if (newGetter != null) { - if (firstOldRef < 0) firstOldRef = i; - Name n2 = new Name(newGetter, n.arguments); - names2[i] = n2; - } - } - } - - // Walk over the new list of names once, in forward order. - // Replace references to 'name' with 'binding'. - // Replace data structure references to the old BMH species with the new. - // This might cause a ripple effect, but it will settle in one pass. - assert(firstOldRef < 0 || firstOldRef > pos); - for (int i = pos+1; i < names2.length; i++) { - if (i <= arity2) continue; - names2[i] = names2[i].replaceNames(names, names2, pos, i); - } - - // (a0, a1, name=a2, a3, a4) => (a0, a1, a3, a4, binding) - int insPos = pos; - for (; insPos+1 < names2.length; insPos++) { - Name n = names2[insPos+1]; - if (n.isSiblingBindingBefore(binding)) { - names2[insPos] = n; - } else { - break; - } - } - names2[insPos] = binding; - - // Since we moved some stuff, maybe update the result reference: - int result2 = result; - if (result2 == pos) - result2 = insPos; - else if (result2 > pos && result2 <= insPos) - result2 -= 1; - - return bindCache[pos] = new LambdaForm(debugName, arity2, names2, result2); + public int hashCode() { + return result + 31 * Arrays.hashCode(names); + } + LambdaFormEditor editor() { + return LambdaFormEditor.lambdaFormEditor(this); } boolean contains(Name name) { @@ -1000,16 +888,16 @@ class LambdaForm { } LambdaForm addArguments(int pos, BasicType... types) { - assert(pos <= arity); + // names array has MH in slot 0; skip it. + int argpos = pos + 1; + assert(argpos <= arity); int length = names.length; int inTypes = types.length; Name[] names2 = Arrays.copyOf(names, length + inTypes); int arity2 = arity + inTypes; int result2 = result; - if (result2 >= arity) + if (result2 >= argpos) result2 += inTypes; - // names array has MH in slot 0; skip it. - int argpos = pos + 1; // Note: The LF constructor will rename names2[argpos...]. // Make space for new arguments (shift temporaries). System.arraycopy(names, argpos, names2, argpos + inTypes, length - argpos); @@ -1102,8 +990,9 @@ class LambdaForm { } NamedFunction(MemberName member, MethodHandle resolvedHandle) { this.member = member; - //resolvedHandle = eraseSubwordTypes(resolvedHandle); this.resolvedHandle = resolvedHandle; + // The following assert is almost always correct, but will fail for corner cases, such as PrivateInvokeTest. + //assert(!isInvokeBasic()); } NamedFunction(MethodType basicInvokerType) { assert(basicInvokerType == basicInvokerType.basicType()) : basicInvokerType; @@ -1114,6 +1003,13 @@ class LambdaForm { // necessary to pass BigArityTest this.member = Invokers.invokeBasicMethod(basicInvokerType); } + assert(isInvokeBasic()); + } + + private boolean isInvokeBasic() { + return member != null && + member.isMethodHandleInvoke() && + "invokeBasic".equals(member.getName()); } // The next 3 constructors are used to break circular dependencies on MH.invokeStatic, etc. @@ -1169,7 +1065,7 @@ class LambdaForm { if (LambdaForm.signatureReturn(sig) == V_TYPE) srcType = srcType.changeReturnType(void.class); MethodTypeForm typeForm = srcType.form(); - typeForm.namedFunctionInvoker = DirectMethodHandle.make(m); + typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, DirectMethodHandle.make(m)); } } } @@ -1179,85 +1075,104 @@ class LambdaForm { /** void return type invokers. */ @Hidden static Object invoke__V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 0); + assert(arityCheck(0, void.class, mh, a)); mh.invokeBasic(); return null; } @Hidden static Object invoke_L_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 1); + assert(arityCheck(1, void.class, mh, a)); mh.invokeBasic(a[0]); return null; } @Hidden static Object invoke_LL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 2); + assert(arityCheck(2, void.class, mh, a)); mh.invokeBasic(a[0], a[1]); return null; } @Hidden static Object invoke_LLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 3); + assert(arityCheck(3, void.class, mh, a)); mh.invokeBasic(a[0], a[1], a[2]); return null; } @Hidden static Object invoke_LLLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 4); + assert(arityCheck(4, void.class, mh, a)); mh.invokeBasic(a[0], a[1], a[2], a[3]); return null; } @Hidden static Object invoke_LLLLL_V(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 5); + assert(arityCheck(5, void.class, mh, a)); mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]); return null; } /** Object return type invokers. */ @Hidden static Object invoke__L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 0); + assert(arityCheck(0, mh, a)); return mh.invokeBasic(); } @Hidden static Object invoke_L_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 1); + assert(arityCheck(1, mh, a)); return mh.invokeBasic(a[0]); } @Hidden static Object invoke_LL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 2); + assert(arityCheck(2, mh, a)); return mh.invokeBasic(a[0], a[1]); } @Hidden static Object invoke_LLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 3); + assert(arityCheck(3, mh, a)); return mh.invokeBasic(a[0], a[1], a[2]); } @Hidden static Object invoke_LLLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 4); + assert(arityCheck(4, mh, a)); return mh.invokeBasic(a[0], a[1], a[2], a[3]); } @Hidden static Object invoke_LLLLL_L(MethodHandle mh, Object[] a) throws Throwable { - assert(a.length == 5); + assert(arityCheck(5, mh, a)); return mh.invokeBasic(a[0], a[1], a[2], a[3], a[4]); } + private static boolean arityCheck(int arity, MethodHandle mh, Object[] a) { + return arityCheck(arity, Object.class, mh, a); + } + private static boolean arityCheck(int arity, Class rtype, MethodHandle mh, Object[] a) { + assert(a.length == arity) + : Arrays.asList(a.length, arity); + assert(mh.type().basicType() == MethodType.genericMethodType(arity).changeReturnType(rtype)) + : Arrays.asList(mh, rtype, arity); + MemberName member = mh.internalMemberName(); + if (member != null && member.getName().equals("invokeBasic") && member.isMethodHandleInvoke()) { + assert(arity > 0); + assert(a[0] instanceof MethodHandle); + MethodHandle mh2 = (MethodHandle) a[0]; + assert(mh2.type().basicType() == MethodType.genericMethodType(arity-1).changeReturnType(rtype)) + : Arrays.asList(member, mh2, rtype, arity); + } + return true; + } static final MethodType INVOKER_METHOD_TYPE = MethodType.methodType(Object.class, MethodHandle.class, Object[].class); private static MethodHandle computeInvoker(MethodTypeForm typeForm) { - MethodHandle mh = typeForm.namedFunctionInvoker; + typeForm = typeForm.basicType().form(); // normalize to basic type + MethodHandle mh = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV); if (mh != null) return mh; MemberName invoker = InvokerBytecodeGenerator.generateNamedFunctionInvoker(typeForm); // this could take a while mh = DirectMethodHandle.make(invoker); - MethodHandle mh2 = typeForm.namedFunctionInvoker; + MethodHandle mh2 = typeForm.cachedMethodHandle(MethodTypeForm.MH_NF_INV); if (mh2 != null) return mh2; // benign race if (!mh.type().equals(INVOKER_METHOD_TYPE)) throw newInternalError(mh.debugString()); - return typeForm.namedFunctionInvoker = mh; + return typeForm.setCachedMethodHandle(MethodTypeForm.MH_NF_INV, mh); } @Hidden @@ -1365,6 +1280,11 @@ class LambdaForm { public boolean isConstantZero() { return this.equals(constantZero(returnType())); } + + public MethodHandleImpl.Intrinsic intrinsicName() { + return resolvedHandle == null ? MethodHandleImpl.Intrinsic.NONE + : resolvedHandle.intrinsicName(); + } } public static String basicTypeSignature(MethodType type) { @@ -1411,6 +1331,7 @@ class LambdaForm { final BasicType type; private short index; final NamedFunction function; + final Object constraint; // additional type information, if not null @Stable final Object[] arguments; private Name(int index, BasicType type, NamedFunction function, Object[] arguments) { @@ -1418,8 +1339,18 @@ class LambdaForm { this.type = type; this.function = function; this.arguments = arguments; + this.constraint = null; assert(this.index == index); } + private Name(Name that, Object constraint) { + this.index = that.index; + this.type = that.type; + this.function = that.function; + this.arguments = that.arguments; + this.constraint = constraint; + assert(constraint == null || isParam()); // only params have constraints + assert(constraint == null || constraint instanceof BoundMethodHandle.SpeciesData || constraint instanceof Class); + } Name(MethodHandle function, Object... arguments) { this(new NamedFunction(function), arguments); } @@ -1431,7 +1362,7 @@ class LambdaForm { this(new NamedFunction(function), arguments); } Name(NamedFunction function, Object... arguments) { - this(-1, function.returnType(), function, arguments = arguments.clone()); + this(-1, function.returnType(), function, arguments = Arrays.copyOf(arguments, arguments.length, Object[].class)); assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString(); for (int i = 0; i < arguments.length; i++) assert(typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString(); @@ -1467,7 +1398,11 @@ class LambdaForm { } Name cloneWithIndex(int i) { Object[] newArguments = (arguments == null) ? null : arguments.clone(); - return new Name(i, type, function, newArguments); + return new Name(i, type, function, newArguments).withConstraint(constraint); + } + Name withConstraint(Object constraint) { + if (constraint == this.constraint) return this; + return new Name(this, constraint); } Name replaceName(Name oldName, Name newName) { // FIXME: use replaceNames uniformly if (oldName == newName) return this; @@ -1487,7 +1422,11 @@ class LambdaForm { if (!replaced) return this; return new Name(function, arguments); } + /** In the arguments of this Name, replace oldNames[i] pairwise by newNames[i]. + * Limit such replacements to {@code start<=i= end) return this; @SuppressWarnings("LocalVariableHidesMemberVariable") Object[] arguments = this.arguments; boolean replaced = false; @@ -1539,9 +1478,17 @@ class LambdaForm { return (isParam()?"a":"t")+(index >= 0 ? index : System.identityHashCode(this))+":"+typeChar(); } public String debugString() { - String s = toString(); + String s = paramString(); return (function == null) ? s : s + "=" + exprString(); } + public String paramString() { + String s = toString(); + Object c = constraint; + if (c == null) + return s; + if (c instanceof Class) c = ((Class)c).getSimpleName(); + return s + "/" + c; + } public String exprString() { if (function == null) return toString(); StringBuilder buf = new StringBuilder(function.toString()); @@ -1572,34 +1519,6 @@ class LambdaForm { return true; } - /** - * Does this Name precede the given binding node in some canonical order? - * This predicate is used to order data bindings (via insertion sort) - * with some stability. - */ - boolean isSiblingBindingBefore(Name binding) { - assert(!binding.isParam()); - if (isParam()) return true; - if (function.equals(binding.function) && - arguments.length == binding.arguments.length) { - boolean sawInt = false; - for (int i = 0; i < arguments.length; i++) { - Object a1 = arguments[i]; - Object a2 = binding.arguments[i]; - if (!a1.equals(a2)) { - if (a1 instanceof Integer && a2 instanceof Integer) { - if (sawInt) continue; - sawInt = true; - if ((int)a1 < (int)a2) continue; // still might be true - } - return false; - } - } - return sawInt; - } - return false; - } - /** Return the index of the last occurrence of n in the argument array. * Return -1 if the name is not used. */ @@ -1690,6 +1609,7 @@ class LambdaForm { static Name internArgument(Name n) { assert(n.isParam()) : "not param: " + n; assert(n.index < INTERNED_ARGUMENT_LIMIT); + if (n.constraint != null) return n; return argument(n.index, n.type); } static Name[] arguments(int extra, String types) { @@ -1858,37 +1778,6 @@ class LambdaForm { @interface Hidden { } - -/* - // Smoke-test for the invokers used in this file. - static void testMethodHandleLinkers() throws Throwable { - MemberName.Factory lookup = MemberName.getFactory(); - MemberName asList_MN = new MemberName(Arrays.class, "asList", - MethodType.methodType(List.class, Object[].class), - REF_invokeStatic); - //MethodHandleNatives.resolve(asList_MN, null); - asList_MN = lookup.resolveOrFail(asList_MN, REF_invokeStatic, null, NoSuchMethodException.class); - System.out.println("about to call "+asList_MN); - Object[] abc = { "a", "bc" }; - List lst = (List) MethodHandle.linkToStatic(abc, asList_MN); - System.out.println("lst="+lst); - MemberName toString_MN = new MemberName(Object.class.getMethod("toString")); - String s1 = (String) MethodHandle.linkToVirtual(lst, toString_MN); - toString_MN = new MemberName(Object.class.getMethod("toString"), true); - String s2 = (String) MethodHandle.linkToSpecial(lst, toString_MN); - System.out.println("[s1,s2,lst]="+Arrays.asList(s1, s2, lst.toString())); - MemberName toArray_MN = new MemberName(List.class.getMethod("toArray")); - Object[] arr = (Object[]) MethodHandle.linkToInterface(lst, toArray_MN); - System.out.println("toArray="+Arrays.toString(arr)); - } - static { try { testMethodHandleLinkers(); } catch (Throwable ex) { throw new RuntimeException(ex); } } - // Requires these definitions in MethodHandle: - static final native Object linkToStatic(Object x1, MemberName mn) throws Throwable; - static final native Object linkToVirtual(Object x1, MemberName mn) throws Throwable; - static final native Object linkToSpecial(Object x1, MemberName mn) throws Throwable; - static final native Object linkToInterface(Object x1, MemberName mn) throws Throwable; - */ - private static final HashMap DEBUG_NAME_COUNTERS; static { if (debugEnabled()) @@ -1901,7 +1790,7 @@ class LambdaForm { static { createIdentityForms(); if (USE_PREDEFINED_INTERPRET_METHODS) - PREPARED_FORMS.putAll(computeInitialPreparedForms()); + computeInitialPreparedForms(); NamedFunction.initializeInvokers(); } diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuffer.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuffer.java new file mode 100644 index 00000000000..872a2a59921 --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormBuffer.java @@ -0,0 +1,401 @@ +/* + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.invoke; + +import java.util.ArrayList; +import java.util.Arrays; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; + +/** Working storage for an LF that is being transformed. + * Similarly to a StringBuffer, the editing can take place in multiple steps. + */ +final class LambdaFormBuffer { + private int arity, length; + private Name[] names; + private Name[] originalNames; // snapshot of pre-transaction names + private byte flags; + private int firstChange; + private Name resultName; + private String debugName; + private ArrayList dups; + + private static final int F_TRANS = 0x10, F_OWNED = 0x03; + + LambdaFormBuffer(LambdaForm lf) { + this(lf.arity, lf.names, lf.result); + debugName = lf.debugName; + assert(lf.nameRefsAreLegal()); + } + + private LambdaFormBuffer(int arity, Name[] names, int result) { + this.arity = arity; + setNames(names); + if (result == LAST_RESULT) result = length - 1; + if (result >= 0 && names[result].type != V_TYPE) + resultName = names[result]; + } + + private LambdaForm lambdaForm() { + assert(!inTrans()); // need endEdit call to tidy things up + return new LambdaForm(debugName, arity, nameArray(), resultIndex()); + } + + Name name(int i) { + assert(i < length); + return names[i]; + } + + Name[] nameArray() { + return Arrays.copyOf(names, length); + } + + int resultIndex() { + if (resultName == null) return VOID_RESULT; + int index = indexOf(resultName, names); + assert(index >= 0); + return index; + } + + void setNames(Name[] names2) { + names = originalNames = names2; // keep a record of where everything was to start with + length = names2.length; + flags = 0; + } + + private boolean verifyArity() { + for (int i = 0; i < arity && i < firstChange; i++) { + assert(names[i].isParam()) : "#" + i + "=" + names[i]; + } + for (int i = arity; i < length; i++) { + assert(!names[i].isParam()) : "#" + i + "=" + names[i]; + } + for (int i = length; i < names.length; i++) { + assert(names[i] == null) : "#" + i + "=" + names[i]; + } + // check resultName also + if (resultName != null) { + int resultIndex = indexOf(resultName, names); + assert(resultIndex >= 0) : "not found: " + resultName.exprString() + Arrays.asList(names); + assert(names[resultIndex] == resultName); + } + return true; + } + + private boolean verifyFirstChange() { + assert(inTrans()); + for (int i = 0; i < length; i++) { + if (names[i] != originalNames[i]) { + assert(firstChange == i) : Arrays.asList(firstChange, i, originalNames[i].exprString(), Arrays.asList(names)); + return true; + } + } + assert(firstChange == length) : Arrays.asList(firstChange, Arrays.asList(names)); + return true; + } + + private static int indexOf(NamedFunction fn, NamedFunction[] fns) { + for (int i = 0; i < fns.length; i++) { + if (fns[i] == fn) return i; + } + return -1; + } + + private static int indexOf(Name n, Name[] ns) { + for (int i = 0; i < ns.length; i++) { + if (ns[i] == n) return i; + } + return -1; + } + + boolean inTrans() { + return (flags & F_TRANS) != 0; + } + + int ownedCount() { + return flags & F_OWNED; + } + + void growNames(int insertPos, int growLength) { + int oldLength = length; + int newLength = oldLength + growLength; + int oc = ownedCount(); + if (oc == 0 || newLength > names.length) { + names = Arrays.copyOf(names, (names.length + growLength) * 5 / 4); + if (oc == 0) { + flags++; + oc++; + assert(ownedCount() == oc); + } + } + if (originalNames != null && originalNames.length < names.length) { + originalNames = Arrays.copyOf(originalNames, names.length); + if (oc == 1) { + flags++; + oc++; + assert(ownedCount() == oc); + } + } + if (growLength == 0) return; + int insertEnd = insertPos + growLength; + int tailLength = oldLength - insertPos; + System.arraycopy(names, insertPos, names, insertEnd, tailLength); + Arrays.fill(names, insertPos, insertEnd, null); + if (originalNames != null) { + System.arraycopy(originalNames, insertPos, originalNames, insertEnd, tailLength); + Arrays.fill(originalNames, insertPos, insertEnd, null); + } + length = newLength; + if (firstChange >= insertPos) { + firstChange += growLength; + } + } + + int lastIndexOf(Name n) { + int result = -1; + for (int i = 0; i < length; i++) { + if (names[i] == n) result = i; + } + return result; + } + + /** We have just overwritten the name at pos1 with the name at pos2. + * This means that there are two copies of the name, which we will have to fix later. + */ + private void noteDuplicate(int pos1, int pos2) { + Name n = names[pos1]; + assert(n == names[pos2]); + assert(originalNames[pos1] != null); // something was replaced at pos1 + assert(originalNames[pos2] == null || originalNames[pos2] == n); + if (dups == null) { + dups = new ArrayList<>(); + } + dups.add(n); + } + + /** Replace duplicate names by nulls, and remove all nulls. */ + private void clearDuplicatesAndNulls() { + if (dups != null) { + // Remove duplicates. + assert(ownedCount() >= 1); + for (Name dup : dups) { + for (int i = firstChange; i < length; i++) { + if (names[i] == dup && originalNames[i] != dup) { + names[i] = null; + assert(Arrays.asList(names).contains(dup)); + break; // kill only one dup + } + } + } + dups.clear(); + } + // Now that we are done with originalNames, remove "killed" names. + int oldLength = length; + for (int i = firstChange; i < length; i++) { + if (names[i] == null) { + System.arraycopy(names, i + 1, names, i, (--length - i)); + --i; // restart loop at this position + } + } + if (length < oldLength) { + Arrays.fill(names, length, oldLength, null); + } + assert(!Arrays.asList(names).subList(0, length).contains(null)); + } + + /** Create a private, writable copy of names. + * Preserve the original copy, for reference. + */ + void startEdit() { + assert(verifyArity()); + int oc = ownedCount(); + assert(!inTrans()); // no nested transactions + flags |= F_TRANS; + Name[] oldNames = names; + Name[] ownBuffer = (oc == 2 ? originalNames : null); + assert(ownBuffer != oldNames); + if (ownBuffer != null && ownBuffer.length >= length) { + names = copyNamesInto(ownBuffer); + } else { + // make a new buffer to hold the names + final int SLOP = 2; + names = Arrays.copyOf(oldNames, Math.max(length + SLOP, oldNames.length)); + if (oc < 2) ++flags; + assert(ownedCount() == oc + 1); + } + originalNames = oldNames; + assert(originalNames != names); + firstChange = length; + assert(inTrans()); + } + + private void changeName(int i, Name name) { + assert(inTrans()); + assert(i < length); + Name oldName = names[i]; + assert(oldName == originalNames[i]); // no multiple changes + assert(verifyFirstChange()); + if (ownedCount() == 0) + growNames(0, 0); + names[i] = name; + if (firstChange > i) { + firstChange = i; + } + if (resultName != null && resultName == oldName) { + resultName = name; + } + } + + /** Change the result name. Null means a void result. */ + void setResult(Name name) { + assert(name == null || lastIndexOf(name) >= 0); + resultName = name; + } + + /** Finish a transaction. */ + LambdaForm endEdit() { + assert(verifyFirstChange()); + // Assuming names have been changed pairwise from originalNames[i] to names[i], + // update arguments to ensure referential integrity. + for (int i = Math.max(firstChange, arity); i < length; i++) { + Name name = names[i]; + if (name == null) continue; // space for removed duplicate + Name newName = name.replaceNames(originalNames, names, firstChange, i); + if (newName != name) { + names[i] = newName; + if (resultName == name) { + resultName = newName; + } + } + } + assert(inTrans()); + flags &= ~F_TRANS; + clearDuplicatesAndNulls(); + originalNames = null; + // If any parameters have been changed, then reorder them as needed. + // This is a "sheep-and-goats" stable sort, pushing all non-parameters + // to the right of all parameters. + if (firstChange < arity) { + Name[] exprs = new Name[arity - firstChange]; + int argp = firstChange, exprp = 0; + for (int i = firstChange; i < arity; i++) { + Name name = names[i]; + if (name.isParam()) { + names[argp++] = name; + } else { + exprs[exprp++] = name; + } + } + assert(exprp == (arity - argp)); + // copy the exprs just after the last remaining param + System.arraycopy(exprs, 0, names, argp, exprp); + // adjust arity + arity -= exprp; + } + assert(verifyArity()); + return lambdaForm(); + } + + private Name[] copyNamesInto(Name[] buffer) { + System.arraycopy(names, 0, buffer, 0, length); + Arrays.fill(buffer, length, buffer.length, null); + return buffer; + } + + /** Replace any Name whose function is in oldFns with a copy + * whose function is in the corresponding position in newFns. + * Only do this if the arguments are exactly equal to the given. + */ + LambdaFormBuffer replaceFunctions(NamedFunction[] oldFns, NamedFunction[] newFns, + Object... forArguments) { + assert(inTrans()); + if (oldFns.length == 0) return this; + for (int i = arity; i < length; i++) { + Name n = names[i]; + int nfi = indexOf(n.function, oldFns); + if (nfi >= 0 && Arrays.equals(n.arguments, forArguments)) { + changeName(i, new Name(newFns[nfi], n.arguments)); + } + } + return this; + } + + private void replaceName(int pos, Name binding) { + assert(inTrans()); + assert(verifyArity()); + assert(pos < arity); + Name param = names[pos]; + assert(param.isParam()); + assert(param.type == binding.type); + changeName(pos, binding); + } + + /** Replace a parameter by a fresh parameter. */ + LambdaFormBuffer renameParameter(int pos, Name newParam) { + assert(newParam.isParam()); + replaceName(pos, newParam); + return this; + } + + /** Replace a parameter by a fresh expression. */ + LambdaFormBuffer replaceParameterByNewExpression(int pos, Name binding) { + assert(!binding.isParam()); + assert(lastIndexOf(binding) < 0); // else use replaceParameterByCopy + replaceName(pos, binding); + return this; + } + + /** Replace a parameter by another parameter or expression already in the form. */ + LambdaFormBuffer replaceParameterByCopy(int pos, int valuePos) { + assert(pos != valuePos); + replaceName(pos, names[valuePos]); + noteDuplicate(pos, valuePos); // temporarily, will occur twice in the names array + return this; + } + + private void insertName(int pos, Name expr, boolean isParameter) { + assert(inTrans()); + assert(verifyArity()); + assert(isParameter ? pos <= arity : pos >= arity); + growNames(pos, 1); + if (isParameter) arity += 1; + changeName(pos, expr); + } + + /** Insert a fresh expression. */ + LambdaFormBuffer insertExpression(int pos, Name expr) { + assert(!expr.isParam()); + insertName(pos, expr, false); + return this; + } + + /** Insert a fresh parameter. */ + LambdaFormBuffer insertParameter(int pos, Name param) { + assert(param.isParam()); + insertName(pos, param, true); + return this; + } +} diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java new file mode 100644 index 00000000000..1c29d73b4cc --- /dev/null +++ b/jdk/src/java.base/share/classes/java/lang/invoke/LambdaFormEditor.java @@ -0,0 +1,825 @@ +/* + * 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package java.lang.invoke; + +import java.util.Arrays; +import static java.lang.invoke.LambdaForm.*; +import static java.lang.invoke.LambdaForm.BasicType.*; +import static java.lang.invoke.MethodHandleImpl.Intrinsic; +import java.util.Collections; +import java.util.concurrent.ConcurrentHashMap; + +import sun.invoke.util.Wrapper; + +/** Transforms on LFs. + * A lambda-form editor can derive new LFs from its base LF. + * The editor can cache derived LFs, which simplifies the reuse of their underlying bytecodes. + * To support this caching, a LF has an optional pointer to its editor. + */ +class LambdaFormEditor { + final LambdaForm lambdaForm; + + private LambdaFormEditor(LambdaForm lambdaForm) { + this.lambdaForm = lambdaForm; + } + + // Factory method. + static LambdaFormEditor lambdaFormEditor(LambdaForm lambdaForm) { + // TO DO: Consider placing intern logic here, to cut down on duplication. + // lambdaForm = findPreexistingEquivalent(lambdaForm) + return new LambdaFormEditor(lambdaForm); + } + + /** A description of a cached transform, possibly associated with the result of the transform. + * The logical content is a sequence of byte values, starting with a Kind.ordinal value. + * The sequence is unterminated, ending with an indefinite number of zero bytes. + * Sequences that are simple (short enough and with small enough values) pack into a 64-bit long. + */ + private static final class Transform { + final long packedBytes; + final byte[] fullBytes; + final LambdaForm result; // result of transform, or null, if there is none available + + private enum Kind { + NO_KIND, // necessary because ordinal must be greater than zero + BIND_ARG, ADD_ARG, DUP_ARG, + SPREAD_ARGS, + FILTER_ARG, FILTER_RETURN, FILTER_RETURN_TO_ZERO, + COLLECT_ARGS, COLLECT_ARGS_TO_VOID, COLLECT_ARGS_TO_ARRAY, + FOLD_ARGS, FOLD_ARGS_TO_VOID, + PERMUTE_ARGS + //maybe add more for guard with test, catch exception, pointwise type conversions + } + + private static final boolean STRESS_TEST = false; // turn on to disable most packing + private static final int + PACKED_BYTE_SIZE = (STRESS_TEST ? 2 : 4), + PACKED_BYTE_MASK = (1 << PACKED_BYTE_SIZE) - 1, + PACKED_BYTE_MAX_LENGTH = (STRESS_TEST ? 3 : 64 / PACKED_BYTE_SIZE); + + private static long packedBytes(byte[] bytes) { + if (bytes.length > PACKED_BYTE_MAX_LENGTH) return 0; + long pb = 0; + int bitset = 0; + for (int i = 0; i < bytes.length; i++) { + int b = bytes[i] & 0xFF; + bitset |= b; + pb |= (long)b << (i * PACKED_BYTE_SIZE); + } + if (!inRange(bitset)) + return 0; + return pb; + } + private static long packedBytes(int b0, int b1) { + assert(inRange(b0 | b1)); + return ( (b0 << 0*PACKED_BYTE_SIZE) + | (b1 << 1*PACKED_BYTE_SIZE)); + } + private static long packedBytes(int b0, int b1, int b2) { + assert(inRange(b0 | b1 | b2)); + return ( (b0 << 0*PACKED_BYTE_SIZE) + | (b1 << 1*PACKED_BYTE_SIZE) + | (b2 << 2*PACKED_BYTE_SIZE)); + } + private static long packedBytes(int b0, int b1, int b2, int b3) { + assert(inRange(b0 | b1 | b2 | b3)); + return ( (b0 << 0*PACKED_BYTE_SIZE) + | (b1 << 1*PACKED_BYTE_SIZE) + | (b2 << 2*PACKED_BYTE_SIZE) + | (b3 << 3*PACKED_BYTE_SIZE)); + } + private static boolean inRange(int bitset) { + assert((bitset & 0xFF) == bitset); // incoming values must fit in *unsigned* byte + return ((bitset & ~PACKED_BYTE_MASK) == 0); + } + private static byte[] fullBytes(int... byteValues) { + byte[] bytes = new byte[byteValues.length]; + int i = 0; + for (int bv : byteValues) { + bytes[i++] = bval(bv); + } + assert(packedBytes(bytes) == 0); + return bytes; + } + + private byte byteAt(int i) { + long pb = packedBytes; + if (pb == 0) { + if (i >= fullBytes.length) return 0; + return fullBytes[i]; + } + assert(fullBytes == null); + if (i > PACKED_BYTE_MAX_LENGTH) return 0; + int pos = (i * PACKED_BYTE_SIZE); + return (byte)((pb >>> pos) & PACKED_BYTE_MASK); + } + + Kind kind() { return Kind.values()[byteAt(0)]; } + + private Transform(long packedBytes, byte[] fullBytes, LambdaForm result) { + this.packedBytes = packedBytes; + this.fullBytes = fullBytes; + this.result = result; + } + private Transform(long packedBytes) { + this(packedBytes, null, null); + assert(packedBytes != 0); + } + private Transform(byte[] fullBytes) { + this(0, fullBytes, null); + } + + private static byte bval(int b) { + assert((b & 0xFF) == b); // incoming value must fit in *unsigned* byte + return (byte)b; + } + private static byte bval(Kind k) { + return bval(k.ordinal()); + } + static Transform of(Kind k, int b1) { + byte b0 = bval(k); + if (inRange(b0 | b1)) + return new Transform(packedBytes(b0, b1)); + else + return new Transform(fullBytes(b0, b1)); + } + static Transform of(Kind k, int b1, int b2) { + byte b0 = (byte) k.ordinal(); + if (inRange(b0 | b1 | b2)) + return new Transform(packedBytes(b0, b1, b2)); + else + return new Transform(fullBytes(b0, b1, b2)); + } + static Transform of(Kind k, int b1, int b2, int b3) { + byte b0 = (byte) k.ordinal(); + if (inRange(b0 | b1 | b2 | b3)) + return new Transform(packedBytes(b0, b1, b2, b3)); + else + return new Transform(fullBytes(b0, b1, b2, b3)); + } + private static final byte[] NO_BYTES = {}; + static Transform of(Kind k, int... b123) { + return ofBothArrays(k, b123, NO_BYTES); + } + static Transform of(Kind k, int b1, byte[] b234) { + return ofBothArrays(k, new int[]{ b1 }, b234); + } + static Transform of(Kind k, int b1, int b2, byte[] b345) { + return ofBothArrays(k, new int[]{ b1, b2 }, b345); + } + private static Transform ofBothArrays(Kind k, int[] b123, byte[] b456) { + byte[] fullBytes = new byte[1 + b123.length + b456.length]; + int i = 0; + fullBytes[i++] = bval(k); + for (int bv : b123) { + fullBytes[i++] = bval(bv); + } + for (byte bv : b456) { + fullBytes[i++] = bv; + } + long packedBytes = packedBytes(fullBytes); + if (packedBytes != 0) + return new Transform(packedBytes); + else + return new Transform(fullBytes); + } + + Transform withResult(LambdaForm result) { + return new Transform(this.packedBytes, this.fullBytes, result); + } + + @Override + public boolean equals(Object obj) { + return obj instanceof Transform && equals((Transform)obj); + } + public boolean equals(Transform that) { + return this.packedBytes == that.packedBytes && Arrays.equals(this.fullBytes, that.fullBytes); + } + @Override + public int hashCode() { + if (packedBytes != 0) { + assert(fullBytes == null); + return Long.hashCode(packedBytes); + } + return Arrays.hashCode(fullBytes); + } + @Override + public String toString() { + StringBuilder buf = new StringBuilder(); + long bits = packedBytes; + if (bits != 0) { + buf.append("("); + while (bits != 0) { + buf.append(bits & PACKED_BYTE_MASK); + bits >>>= PACKED_BYTE_SIZE; + if (bits != 0) buf.append(","); + } + buf.append(")"); + } + if (fullBytes != null) { + buf.append("unpacked"); + buf.append(Arrays.toString(fullBytes)); + } + if (result != null) { + buf.append(" result="); + buf.append(result); + } + return buf.toString(); + } + } + + /** Find a previously cached transform equivalent to the given one, and return its result. */ + private LambdaForm getInCache(Transform key) { + assert(key.result == null); + // The transformCache is one of null, Transform, Transform[], or ConcurrentHashMap. + Object c = lambdaForm.transformCache; + Transform k = null; + if (c instanceof ConcurrentHashMap) { + @SuppressWarnings("unchecked") + ConcurrentHashMap m = (ConcurrentHashMap) c; + k = m.get(key); + } else if (c == null) { + return null; + } else if (c instanceof Transform) { + // one-element cache avoids overhead of an array + Transform t = (Transform)c; + if (t.equals(key)) k = t; + } else { + Transform[] ta = (Transform[])c; + for (int i = 0; i < ta.length; i++) { + Transform t = ta[i]; + if (t == null) break; + if (t.equals(key)) { k = t; break; } + } + } + assert(k == null || key.equals(k)); + return k == null ? null : k.result; + } + + /** Arbitrary but reasonable limits on Transform[] size for cache. */ + private static final int MIN_CACHE_ARRAY_SIZE = 4, MAX_CACHE_ARRAY_SIZE = 16; + + /** Cache a transform with its result, and return that result. + * But if an equivalent transform has already been cached, return its result instead. + */ + private LambdaForm putInCache(Transform key, LambdaForm form) { + key = key.withResult(form); + for (int pass = 0; ; pass++) { + Object c = lambdaForm.transformCache; + if (c instanceof ConcurrentHashMap) { + @SuppressWarnings("unchecked") + ConcurrentHashMap m = (ConcurrentHashMap) c; + Transform k = m.putIfAbsent(key, key); + return k != null ? k.result : form; + } + assert(pass == 0); + synchronized (lambdaForm) { + c = lambdaForm.transformCache; + if (c instanceof ConcurrentHashMap) + continue; + if (c == null) { + lambdaForm.transformCache = key; + return form; + } + Transform[] ta; + if (c instanceof Transform) { + Transform k = (Transform)c; + if (k.equals(key)) { + return k.result; + } + // expand one-element cache to small array + ta = new Transform[MIN_CACHE_ARRAY_SIZE]; + ta[0] = k; + lambdaForm.transformCache = c = ta; + } else { + // it is already expanded + ta = (Transform[])c; + } + int len = ta.length; + int i; + for (i = 0; i < len; i++) { + Transform k = ta[i]; + if (k == null) { + break; + } + if (k.equals(key)) { + return k.result; + } + } + if (i < len) { + // just fall through to cache update + } else if (len < MAX_CACHE_ARRAY_SIZE) { + len = Math.min(len * 2, MAX_CACHE_ARRAY_SIZE); + ta = Arrays.copyOf(ta, len); + lambdaForm.transformCache = ta; + } else { + ConcurrentHashMap m = new ConcurrentHashMap<>(MAX_CACHE_ARRAY_SIZE * 2); + for (Transform k : ta) { + m.put(k, k); + } + lambdaForm.transformCache = m; + // The second iteration will update for this query, concurrently. + continue; + } + ta[i] = key; + return form; + } + } + } + + private LambdaFormBuffer buffer() { + return new LambdaFormBuffer(lambdaForm); + } + + /// Editing methods for method handles. These need to have fast paths. + + private BoundMethodHandle.SpeciesData oldSpeciesData() { + return BoundMethodHandle.speciesData(lambdaForm); + } + private BoundMethodHandle.SpeciesData newSpeciesData(BasicType type) { + return oldSpeciesData().extendWith(type); + } + + BoundMethodHandle bindArgumentL(BoundMethodHandle mh, int pos, Object value) { + assert(mh.speciesData() == oldSpeciesData()); + BasicType bt = L_TYPE; + MethodType type2 = bindArgumentType(mh, pos, bt); + LambdaForm form2 = bindArgumentForm(1+pos); + return mh.copyWithExtendL(type2, form2, value); + } + BoundMethodHandle bindArgumentI(BoundMethodHandle mh, int pos, int value) { + assert(mh.speciesData() == oldSpeciesData()); + BasicType bt = I_TYPE; + MethodType type2 = bindArgumentType(mh, pos, bt); + LambdaForm form2 = bindArgumentForm(1+pos); + return mh.copyWithExtendI(type2, form2, value); + } + + BoundMethodHandle bindArgumentJ(BoundMethodHandle mh, int pos, long value) { + assert(mh.speciesData() == oldSpeciesData()); + BasicType bt = J_TYPE; + MethodType type2 = bindArgumentType(mh, pos, bt); + LambdaForm form2 = bindArgumentForm(1+pos); + return mh.copyWithExtendJ(type2, form2, value); + } + + BoundMethodHandle bindArgumentF(BoundMethodHandle mh, int pos, float value) { + assert(mh.speciesData() == oldSpeciesData()); + BasicType bt = F_TYPE; + MethodType type2 = bindArgumentType(mh, pos, bt); + LambdaForm form2 = bindArgumentForm(1+pos); + return mh.copyWithExtendF(type2, form2, value); + } + + BoundMethodHandle bindArgumentD(BoundMethodHandle mh, int pos, double value) { + assert(mh.speciesData() == oldSpeciesData()); + BasicType bt = D_TYPE; + MethodType type2 = bindArgumentType(mh, pos, bt); + LambdaForm form2 = bindArgumentForm(1+pos); + return mh.copyWithExtendD(type2, form2, value); + } + + private MethodType bindArgumentType(BoundMethodHandle mh, int pos, BasicType bt) { + assert(mh.form == lambdaForm); + assert(mh.form.names[1+pos].type == bt); + assert(BasicType.basicType(mh.type().parameterType(pos)) == bt); + return mh.type().dropParameterTypes(pos, pos+1); + } + + /// Editing methods for lambda forms. + // Each editing method can (potentially) cache the edited LF so that it can be reused later. + + LambdaForm bindArgumentForm(int pos) { + Transform key = Transform.of(Transform.Kind.BIND_ARG, pos); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.parameterConstraint(0) == newSpeciesData(lambdaForm.parameterType(pos))); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + BoundMethodHandle.SpeciesData oldData = oldSpeciesData(); + BoundMethodHandle.SpeciesData newData = newSpeciesData(lambdaForm.parameterType(pos)); + Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values + Name newBaseAddress; + NamedFunction getter = newData.getterFunction(oldData.fieldCount()); + + if (pos != 0) { + // The newly created LF will run with a different BMH. + // Switch over any pre-existing BMH field references to the new BMH class. + buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress); + newBaseAddress = oldBaseAddress.withConstraint(newData); + buf.renameParameter(0, newBaseAddress); + buf.replaceParameterByNewExpression(pos, new Name(getter, newBaseAddress)); + } else { + // cannot bind the MH arg itself, unless oldData is empty + assert(oldData == BoundMethodHandle.SpeciesData.EMPTY); + newBaseAddress = new Name(L_TYPE).withConstraint(newData); + buf.replaceParameterByNewExpression(0, new Name(getter, newBaseAddress)); + buf.insertParameter(0, newBaseAddress); + } + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm addArgumentForm(int pos, BasicType type) { + Transform key = Transform.of(Transform.Kind.ADD_ARG, pos, type.ordinal()); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity+1); + assert(form.parameterType(pos) == type); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + buf.insertParameter(pos, new Name(type)); + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm dupArgumentForm(int srcPos, int dstPos) { + Transform key = Transform.of(Transform.Kind.DUP_ARG, srcPos, dstPos); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity-1); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + assert(lambdaForm.parameter(srcPos).constraint == null); + assert(lambdaForm.parameter(dstPos).constraint == null); + buf.replaceParameterByCopy(dstPos, srcPos); + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm spreadArgumentsForm(int pos, Class arrayType, int arrayLength) { + Class elementType = arrayType.getComponentType(); + Class erasedArrayType = arrayType; + if (!elementType.isPrimitive()) + erasedArrayType = Object[].class; + BasicType bt = basicType(elementType); + int elementTypeKey = bt.ordinal(); + if (bt.basicTypeClass() != elementType) { + if (elementType.isPrimitive()) { + elementTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal(); + } + } + Transform key = Transform.of(Transform.Kind.SPREAD_ARGS, pos, elementTypeKey, arrayLength); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity - arrayLength + 1); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + assert(pos <= MethodType.MAX_JVM_ARITY); + assert(pos + arrayLength <= lambdaForm.arity); + assert(pos > 0); // cannot spread the MH arg itself + + Name spreadParam = new Name(L_TYPE); + Name checkSpread = new Name(MethodHandleImpl.Lazy.NF_checkSpreadArgument, spreadParam, arrayLength); + + // insert the new expressions + int exprPos = lambdaForm.arity(); + buf.insertExpression(exprPos++, checkSpread); + // adjust the arguments + MethodHandle aload = MethodHandles.arrayElementGetter(erasedArrayType); + for (int i = 0; i < arrayLength; i++) { + Name loadArgument = new Name(aload, spreadParam, i); + buf.insertExpression(exprPos + i, loadArgument); + buf.replaceParameterByCopy(pos + i, exprPos + i); + } + buf.insertParameter(pos, spreadParam); + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm collectArgumentsForm(int pos, MethodType collectorType) { + int collectorArity = collectorType.parameterCount(); + boolean dropResult = (collectorType.returnType() == void.class); + if (collectorArity == 1 && !dropResult) { + return filterArgumentForm(pos, basicType(collectorType.parameterType(0))); + } + BasicType[] newTypes = BasicType.basicTypes(collectorType.parameterList()); + Transform.Kind kind = (dropResult + ? Transform.Kind.COLLECT_ARGS_TO_VOID + : Transform.Kind.COLLECT_ARGS); + if (dropResult && collectorArity == 0) pos = 1; // pure side effect + Transform key = Transform.of(kind, pos, collectorArity, BasicType.basicTypesOrd(newTypes)); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity - (dropResult ? 0 : 1) + collectorArity); + return form; + } + form = makeArgumentCombinationForm(pos, collectorType, false, dropResult); + return putInCache(key, form); + } + + LambdaForm collectArgumentArrayForm(int pos, MethodHandle arrayCollector) { + MethodType collectorType = arrayCollector.type(); + int collectorArity = collectorType.parameterCount(); + assert(arrayCollector.intrinsicName() == Intrinsic.NEW_ARRAY); + Class arrayType = collectorType.returnType(); + Class elementType = arrayType.getComponentType(); + BasicType argType = basicType(elementType); + int argTypeKey = argType.ordinal(); + if (argType.basicTypeClass() != elementType) { + // return null if it requires more metadata (like String[].class) + if (!elementType.isPrimitive()) + return null; + argTypeKey = TYPE_LIMIT + Wrapper.forPrimitiveType(elementType).ordinal(); + } + assert(collectorType.parameterList().equals(Collections.nCopies(collectorArity, elementType))); + Transform.Kind kind = Transform.Kind.COLLECT_ARGS_TO_ARRAY; + Transform key = Transform.of(kind, pos, collectorArity, argTypeKey); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity - 1 + collectorArity); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + assert(pos + 1 <= lambdaForm.arity); + assert(pos > 0); // cannot filter the MH arg itself + + Name[] newParams = new Name[collectorArity]; + for (int i = 0; i < collectorArity; i++) { + newParams[i] = new Name(pos + i, argType); + } + Name callCombiner = new Name(arrayCollector, (Object[]) /*...*/ newParams); + + // insert the new expression + int exprPos = lambdaForm.arity(); + buf.insertExpression(exprPos, callCombiner); + + // insert new arguments + int argPos = pos + 1; // skip result parameter + for (Name newParam : newParams) { + buf.insertParameter(argPos++, newParam); + } + assert(buf.lastIndexOf(callCombiner) == exprPos+newParams.length); + buf.replaceParameterByCopy(pos, exprPos+newParams.length); + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm filterArgumentForm(int pos, BasicType newType) { + Transform key = Transform.of(Transform.Kind.FILTER_ARG, pos, newType.ordinal()); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity); + assert(form.parameterType(pos) == newType); + return form; + } + + BasicType oldType = lambdaForm.parameterType(pos); + MethodType filterType = MethodType.methodType(oldType.basicTypeClass(), + newType.basicTypeClass()); + form = makeArgumentCombinationForm(pos, filterType, false, false); + return putInCache(key, form); + } + + private LambdaForm makeArgumentCombinationForm(int pos, + MethodType combinerType, + boolean keepArguments, boolean dropResult) { + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + int combinerArity = combinerType.parameterCount(); + int resultArity = (dropResult ? 0 : 1); + + assert(pos <= MethodType.MAX_JVM_ARITY); + assert(pos + resultArity + (keepArguments ? combinerArity : 0) <= lambdaForm.arity); + assert(pos > 0); // cannot filter the MH arg itself + assert(combinerType == combinerType.basicType()); + assert(combinerType.returnType() != void.class || dropResult); + + BoundMethodHandle.SpeciesData oldData = oldSpeciesData(); + BoundMethodHandle.SpeciesData newData = newSpeciesData(L_TYPE); + + // The newly created LF will run with a different BMH. + // Switch over any pre-existing BMH field references to the new BMH class. + Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values + buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress); + Name newBaseAddress = oldBaseAddress.withConstraint(newData); + buf.renameParameter(0, newBaseAddress); + + Name getCombiner = new Name(newData.getterFunction(oldData.fieldCount()), newBaseAddress); + Object[] combinerArgs = new Object[1 + combinerArity]; + combinerArgs[0] = getCombiner; + Name[] newParams; + if (keepArguments) { + newParams = new Name[0]; + System.arraycopy(lambdaForm.names, pos + resultArity, + combinerArgs, 1, combinerArity); + } else { + newParams = new Name[combinerArity]; + BasicType[] newTypes = basicTypes(combinerType.parameterList()); + for (int i = 0; i < newTypes.length; i++) { + newParams[i] = new Name(pos + i, newTypes[i]); + } + System.arraycopy(newParams, 0, + combinerArgs, 1, combinerArity); + } + Name callCombiner = new Name(combinerType, combinerArgs); + + // insert the two new expressions + int exprPos = lambdaForm.arity(); + buf.insertExpression(exprPos+0, getCombiner); + buf.insertExpression(exprPos+1, callCombiner); + + // insert new arguments, if needed + int argPos = pos + resultArity; // skip result parameter + for (Name newParam : newParams) { + buf.insertParameter(argPos++, newParam); + } + assert(buf.lastIndexOf(callCombiner) == exprPos+1+newParams.length); + if (!dropResult) { + buf.replaceParameterByCopy(pos, exprPos+1+newParams.length); + } + + return buf.endEdit(); + } + + LambdaForm filterReturnForm(BasicType newType, boolean constantZero) { + Transform.Kind kind = (constantZero ? Transform.Kind.FILTER_RETURN_TO_ZERO : Transform.Kind.FILTER_RETURN); + Transform key = Transform.of(kind, newType.ordinal()); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity); + assert(form.returnType() == newType); + return form; + } + LambdaFormBuffer buf = buffer(); + buf.startEdit(); + + int insPos = lambdaForm.names.length; + Name callFilter; + if (constantZero) { + // Synthesize a constant zero value for the given type. + if (newType == V_TYPE) + callFilter = null; + else + callFilter = new Name(constantZero(newType)); + } else { + BoundMethodHandle.SpeciesData oldData = oldSpeciesData(); + BoundMethodHandle.SpeciesData newData = newSpeciesData(L_TYPE); + + // The newly created LF will run with a different BMH. + // Switch over any pre-existing BMH field references to the new BMH class. + Name oldBaseAddress = lambdaForm.parameter(0); // BMH holding the values + buf.replaceFunctions(oldData.getterFunctions(), newData.getterFunctions(), oldBaseAddress); + Name newBaseAddress = oldBaseAddress.withConstraint(newData); + buf.renameParameter(0, newBaseAddress); + + Name getFilter = new Name(newData.getterFunction(oldData.fieldCount()), newBaseAddress); + buf.insertExpression(insPos++, getFilter); + BasicType oldType = lambdaForm.returnType(); + if (oldType == V_TYPE) { + MethodType filterType = MethodType.methodType(newType.basicTypeClass()); + callFilter = new Name(filterType, getFilter); + } else { + MethodType filterType = MethodType.methodType(newType.basicTypeClass(), oldType.basicTypeClass()); + callFilter = new Name(filterType, getFilter, lambdaForm.names[lambdaForm.result]); + } + } + + if (callFilter != null) + buf.insertExpression(insPos++, callFilter); + buf.setResult(callFilter); + + form = buf.endEdit(); + return putInCache(key, form); + } + + LambdaForm foldArgumentsForm(int foldPos, boolean dropResult, MethodType combinerType) { + int combinerArity = combinerType.parameterCount(); + Transform.Kind kind = (dropResult ? Transform.Kind.FOLD_ARGS_TO_VOID : Transform.Kind.FOLD_ARGS); + Transform key = Transform.of(kind, foldPos, combinerArity); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == lambdaForm.arity - (kind == Transform.Kind.FOLD_ARGS ? 1 : 0)); + return form; + } + form = makeArgumentCombinationForm(foldPos, combinerType, true, dropResult); + return putInCache(key, form); + } + + LambdaForm permuteArgumentsForm(int skip, int[] reorder) { + assert(skip == 1); // skip only the leading MH argument, names[0] + int length = lambdaForm.names.length; + int outArgs = reorder.length; + int inTypes = 0; + boolean nullPerm = true; + for (int i = 0; i < reorder.length; i++) { + int inArg = reorder[i]; + if (inArg != i) nullPerm = false; + inTypes = Math.max(inTypes, inArg+1); + } + assert(skip + reorder.length == lambdaForm.arity); + if (nullPerm) return lambdaForm; // do not bother to cache + Transform key = Transform.of(Transform.Kind.PERMUTE_ARGS, reorder); + LambdaForm form = getInCache(key); + if (form != null) { + assert(form.arity == skip+inTypes) : form; + return form; + } + + BasicType[] types = new BasicType[inTypes]; + for (int i = 0; i < outArgs; i++) { + int inArg = reorder[i]; + types[inArg] = lambdaForm.names[skip + i].type; + } + assert (skip + outArgs == lambdaForm.arity); + assert (permutedTypesMatch(reorder, types, lambdaForm.names, skip)); + int pos = 0; + while (pos < outArgs && reorder[pos] == pos) { + pos += 1; + } + Name[] names2 = new Name[length - outArgs + inTypes]; + System.arraycopy(lambdaForm.names, 0, names2, 0, skip + pos); + int bodyLength = length - lambdaForm.arity; + System.arraycopy(lambdaForm.names, skip + outArgs, names2, skip + inTypes, bodyLength); + int arity2 = names2.length - bodyLength; + int result2 = lambdaForm.result; + if (result2 >= 0) { + if (result2 < skip + outArgs) { + result2 = reorder[result2 - skip]; + } else { + result2 = result2 - outArgs + inTypes; + } + } + for (int j = pos; j < outArgs; j++) { + Name n = lambdaForm.names[skip + j]; + int i = reorder[j]; + Name n2 = names2[skip + i]; + if (n2 == null) { + names2[skip + i] = n2 = new Name(types[i]); + } else { + assert (n2.type == types[i]); + } + for (int k = arity2; k < names2.length; k++) { + names2[k] = names2[k].replaceName(n, n2); + } + } + for (int i = skip + pos; i < arity2; i++) { + if (names2[i] == null) { + names2[i] = argument(i, types[i - skip]); + } + } + for (int j = lambdaForm.arity; j < lambdaForm.names.length; j++) { + int i = j - lambdaForm.arity + arity2; + Name n = lambdaForm.names[j]; + Name n2 = names2[i]; + if (n != n2) { + for (int k = i + 1; k < names2.length; k++) { + names2[k] = names2[k].replaceName(n, n2); + } + } + } + + form = new LambdaForm(lambdaForm.debugName, arity2, names2, result2); + return putInCache(key, form); + } + + static boolean permutedTypesMatch(int[] reorder, BasicType[] types, Name[] names, int skip) { + for (int i = 0; i < reorder.length; i++) { + assert (names[skip + i].isParam()); + assert (names[skip + i].type == types[reorder[i]]); + } + return true; + } +} diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java index 9cc901eea7a..d4634c84a8e 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MemberName.java @@ -59,7 +59,7 @@ import java.util.Objects; * and properly use the named member. *

    * When resolved, a member name's internal implementation may include references to JVM metadata. - * This representation is stateless and only decriptive. + * This representation is stateless and only descriptive. * It provides no private information and no capability to use the member. *

    * By contrast, a {@linkplain java.lang.reflect.Method} contains fuller information @@ -327,10 +327,6 @@ import java.util.Objects; assert(getReferenceKind() == oldKind); assert(MethodHandleNatives.refKindIsValid(refKind)); flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT); -// if (isConstructor() && refKind != REF_newInvokeSpecial) -// flags += (IS_METHOD - IS_CONSTRUCTOR); -// else if (refKind == REF_newInvokeSpecial && isMethod()) -// flags += (IS_CONSTRUCTOR - IS_METHOD); return this; } @@ -344,9 +340,11 @@ import java.util.Objects; return !testFlags(mask, 0); } - /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). */ + /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). + * Also returns true for the non-public MH.invokeBasic. + */ public boolean isMethodHandleInvoke() { - final int bits = MH_INVOKE_MODS; + final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC; final int negs = Modifier.STATIC; if (testFlags(bits | negs, bits) && clazz == MethodHandle.class) { @@ -355,7 +353,14 @@ import java.util.Objects; return false; } public static boolean isMethodHandleInvokeName(String name) { - return name.equals("invoke") || name.equals("invokeExact"); + switch (name) { + case "invoke": + case "invokeExact": + case "invokeBasic": // internal sig-poly method + return true; + default: + return false; + } } private static final int MH_INVOKE_MODS = Modifier.NATIVE | Modifier.FINAL | Modifier.PUBLIC; @@ -720,16 +725,8 @@ import java.util.Objects; init(defClass, name, type, flagsMods(IS_FIELD, 0, refKind)); initResolved(false); } - /** Create a field or type name from the given components: Declaring class, name, type. - * The declaring class may be supplied as null if this is to be a bare name and type. - * The modifier flags default to zero. - * The resulting name will in an unresolved state. - */ - public MemberName(Class defClass, String name, Class type, Void unused) { - this(defClass, name, type, REF_NONE); - initResolved(false); - } - /** Create a method or constructor name from the given components: Declaring class, name, type, modifiers. + /** Create a method or constructor name from the given components: + * Declaring class, name, type, reference kind. * It will be a constructor if and only if the name is {@code "<init>"}. * The declaring class may be supplied as null if this is to be a bare name and type. * The last argument is optional, a boolean which requests REF_invokeSpecial. diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java index 19664528f26..e72a07a2aff 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandle.java @@ -27,12 +27,8 @@ package java.lang.invoke; import java.util.*; -import java.lang.invoke.LambdaForm.BasicType; -import sun.invoke.util.*; -import sun.misc.Unsafe; import static java.lang.invoke.MethodHandleStatics.*; -import static java.lang.invoke.LambdaForm.BasicType.*; /** * A method handle is a typed, directly executable reference to an underlying method, @@ -625,15 +621,8 @@ public abstract class MethodHandle { * @see MethodHandles#spreadInvoker */ public Object invokeWithArguments(Object... arguments) throws Throwable { - int argc = arguments == null ? 0 : arguments.length; - @SuppressWarnings("LocalVariableHidesMemberVariable") - MethodType type = type(); - if (type.parameterCount() != argc || isVarargsCollector()) { - // simulate invoke - return asType(MethodType.genericMethodType(argc)).invokeWithArguments(arguments); - } - MethodHandle invoker = type.invokers().varargsInvoker(); - return invoker.invokeExact(this, arguments); + MethodType invocationType = MethodType.genericMethodType(arguments == null ? 0 : arguments.length); + return invocationType.invokers().spreadInvoker(0).invokeExact(asType(invocationType), arguments); } /** @@ -679,7 +668,7 @@ public abstract class MethodHandle { * This method provides the crucial behavioral difference between * {@link #invokeExact invokeExact} and plain, inexact {@link #invoke invoke}. * The two methods - * perform the same steps when the caller's type descriptor exactly m atches + * perform the same steps when the caller's type descriptor exactly matches * the callee's, but when the types differ, plain {@link #invoke invoke} * also calls {@code asType} (or some internal equivalent) in order * to match up the caller's and callee's types. @@ -763,18 +752,26 @@ public abstract class MethodHandle { return this; } // Return 'this.asTypeCache' if the conversion is already memoized. + MethodHandle atc = asTypeCached(newType); + if (atc != null) { + return atc; + } + return asTypeUncached(newType); + } + + private MethodHandle asTypeCached(MethodType newType) { MethodHandle atc = asTypeCache; if (atc != null && newType == atc.type) { return atc; } - return asTypeUncached(newType); + return null; } /** Override this to change asType behavior. */ /*non-public*/ MethodHandle asTypeUncached(MethodType newType) { if (!type.isConvertibleTo(newType)) throw new WrongMethodTypeException("cannot convert "+this+" to "+newType); - return asTypeCache = convertArguments(newType); + return asTypeCache = MethodHandleImpl.makePairwiseConvert(this, newType, true); } /** @@ -867,34 +864,48 @@ assertEquals("[A, B, C]", (String) caToString2.invokeExact('A', "BC".toCharArray * @see #asCollector */ public MethodHandle asSpreader(Class arrayType, int arrayLength) { - asSpreaderChecks(arrayType, arrayLength); - int spreadArgPos = type.parameterCount() - arrayLength; - return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength); + MethodType postSpreadType = asSpreaderChecks(arrayType, arrayLength); + int arity = type().parameterCount(); + int spreadArgPos = arity - arrayLength; + if (USE_LAMBDA_FORM_EDITOR) { + MethodHandle afterSpread = this.asType(postSpreadType); + BoundMethodHandle mh = afterSpread.rebind(); + LambdaForm lform = mh.editor().spreadArgumentsForm(1 + spreadArgPos, arrayType, arrayLength); + MethodType preSpreadType = postSpreadType.replaceParameterTypes(spreadArgPos, arity, arrayType); + return mh.copyWith(preSpreadType, lform); + } else { + return MethodHandleImpl.makeSpreadArguments(this, arrayType, spreadArgPos, arrayLength); + } } - private void asSpreaderChecks(Class arrayType, int arrayLength) { + /** + * See if {@code asSpreader} can be validly called with the given arguments. + * Return the type of the method handle call after spreading but before conversions. + */ + private MethodType asSpreaderChecks(Class arrayType, int arrayLength) { spreadArrayChecks(arrayType, arrayLength); int nargs = type().parameterCount(); if (nargs < arrayLength || arrayLength < 0) throw newIllegalArgumentException("bad spread array length"); - if (arrayType != Object[].class && arrayLength != 0) { - boolean sawProblem = false; - Class arrayElement = arrayType.getComponentType(); - for (int i = nargs - arrayLength; i < nargs; i++) { - if (!MethodType.canConvert(arrayElement, type().parameterType(i))) { - sawProblem = true; + Class arrayElement = arrayType.getComponentType(); + MethodType mtype = type(); + boolean match = true, fail = false; + for (int i = nargs - arrayLength; i < nargs; i++) { + Class ptype = mtype.parameterType(i); + if (ptype != arrayElement) { + match = false; + if (!MethodType.canConvert(arrayElement, ptype)) { + fail = true; break; } } - if (sawProblem) { - ArrayList> ptypes = new ArrayList<>(type().parameterList()); - for (int i = nargs - arrayLength; i < nargs; i++) { - ptypes.set(i, arrayElement); - } - // elicit an error: - this.asType(MethodType.methodType(type().returnType(), ptypes)); - } } + if (match) return mtype; + MethodType needType = mtype.asSpreaderType(arrayType, arrayLength); + if (!fail) return needType; + // elicit an error: + this.asType(needType); + throw newInternalError("should not return", null); } private void spreadArrayChecks(Class arrayType, int arrayLength) { @@ -984,16 +995,31 @@ assertEquals("[123]", (String) longsToString.invokeExact((long)123)); */ public MethodHandle asCollector(Class arrayType, int arrayLength) { asCollectorChecks(arrayType, arrayLength); - int collectArgPos = type().parameterCount()-1; - MethodHandle target = this; - if (arrayType != type().parameterType(collectArgPos)) - target = convertArguments(type().changeParameterType(collectArgPos, arrayType)); - MethodHandle collector = ValueConversions.varargsArray(arrayType, arrayLength); - return MethodHandles.collectArguments(target, collectArgPos, collector); + int collectArgPos = type().parameterCount() - 1; + if (USE_LAMBDA_FORM_EDITOR) { + BoundMethodHandle mh = rebind(); + MethodType resultType = type().asCollectorType(arrayType, arrayLength); + MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength); + LambdaForm lform = mh.editor().collectArgumentArrayForm(1 + collectArgPos, newArray); + if (lform != null) { + return mh.copyWith(resultType, lform); + } + lform = mh.editor().collectArgumentsForm(1 + collectArgPos, newArray.type().basicType()); + return mh.copyWithExtendL(resultType, lform, newArray); + } else { + MethodHandle target = this; + if (arrayType != type().parameterType(collectArgPos)) + target = MethodHandleImpl.makePairwiseConvert(this, type().changeParameterType(collectArgPos, arrayType), true); + MethodHandle collector = MethodHandleImpl.varargsArray(arrayType, arrayLength); + return MethodHandles.collectArguments(target, collectArgPos, collector); + } } - // private API: return true if last param exactly matches arrayType - private boolean asCollectorChecks(Class arrayType, int arrayLength) { + /** + * See if {@code asCollector} can be validly called with the given arguments. + * Return false if the last parameter is not an exact match to arrayType. + */ + /*non-public*/ boolean asCollectorChecks(Class arrayType, int arrayLength) { spreadArrayChecks(arrayType, arrayLength); int nargs = type().parameterCount(); if (nargs != 0) { @@ -1155,7 +1181,7 @@ assertEquals("[three, thee, tee]", Arrays.toString((Object[])ls.get(0))); * @see #asFixedArity */ public MethodHandle asVarargsCollector(Class arrayType) { - Class arrayElement = arrayType.getComponentType(); + arrayType.getClass(); // explicit NPE boolean lastMatch = asCollectorChecks(arrayType, 0); if (isVarargsCollector() && lastMatch) return this; @@ -1257,14 +1283,8 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); * @see MethodHandles#insertArguments */ public MethodHandle bindTo(Object x) { - Class ptype; - @SuppressWarnings("LocalVariableHidesMemberVariable") - MethodType type = type(); - if (type.parameterCount() == 0 || - (ptype = type.parameterType(0)).isPrimitive()) - throw newIllegalArgumentException("no leading reference parameter", x); - x = ptype.cast(x); // throw CCE if needed - return bindReceiver(x); + x = type.leadingReferenceParameter().cast(x); // throw CCE if needed + return bindArgumentL(0, x); } /** @@ -1284,14 +1304,17 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); */ @Override public String toString() { - if (DEBUG_METHOD_HANDLE_NAMES) return debugString(); + if (DEBUG_METHOD_HANDLE_NAMES) return "MethodHandle"+debugString(); return standardString(); } String standardString() { return "MethodHandle"+type; } + /** Return a string with a several lines describing the method handle structure. + * This string would be suitable for display in an IDE debugger. + */ String debugString() { - return standardString()+"/LF="+internalForm()+internalProperties(); + return type+" : "+internalForm()+internalProperties(); } //// Implementation methods. @@ -1300,22 +1323,42 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); // Other transforms to do: convert, explicitCast, permute, drop, filter, fold, GWT, catch + BoundMethodHandle bindArgumentL(int pos, Object value) { + return rebind().bindArgumentL(pos, value); + } + /*non-public*/ MethodHandle setVarargs(MemberName member) throws IllegalAccessException { if (!member.isVarargs()) return this; - int argc = type().parameterCount(); - if (argc != 0) { - Class arrayType = type().parameterType(argc-1); - if (arrayType.isArray()) { - return MethodHandleImpl.makeVarargsCollector(this, arrayType); - } + Class arrayType = type().lastParameterType(); + if (arrayType.isArray()) { + return MethodHandleImpl.makeVarargsCollector(this, arrayType); } throw member.makeAccessException("cannot make variable arity", null); } + /*non-public*/ - MethodHandle viewAsType(MethodType newType) { + MethodHandle viewAsType(MethodType newType, boolean strict) { // No actual conversions, just a new view of the same method. - return MethodHandleImpl.makePairwiseConvert(this, newType, 0); + // Note that this operation must not produce a DirectMethodHandle, + // because retyped DMHs, like any transformed MHs, + // cannot be cracked into MethodHandleInfo. + assert viewAsTypeChecks(newType, strict); + BoundMethodHandle mh = rebind(); + assert(!((MethodHandle)mh instanceof DirectMethodHandle)); + return mh.copyWith(newType, mh.form); + } + + /*non-public*/ + boolean viewAsTypeChecks(MethodType newType, boolean strict) { + if (strict) { + assert(type().isViewableAs(newType, true)) + : Arrays.asList(this, newType); + } else { + assert(type().basicType().isViewableAs(newType.basicType(), true)) + : Arrays.asList(this, newType); + } + return true; } // Decoding @@ -1336,9 +1379,15 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); } /*non-public*/ - MethodHandle withInternalMemberName(MemberName member) { + MethodHandleImpl.Intrinsic intrinsicName() { + // no special intrinsic meaning to most MHs + return MethodHandleImpl.Intrinsic.NONE; + } + + /*non-public*/ + MethodHandle withInternalMemberName(MemberName member, boolean isInvokeSpecial) { if (member != null) { - return MethodHandleImpl.makeWrappedMember(this, member); + return MethodHandleImpl.makeWrappedMember(this, member, isInvokeSpecial); } else if (internalMemberName() == null) { // The required internaMemberName is null, and this MH (like most) doesn't have one. return this; @@ -1362,7 +1411,7 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); /*non-public*/ Object internalProperties() { - // Override to something like "/FOO=bar" + // Override to something to follow this.form, like "\n& FOO=bar" return ""; } @@ -1370,95 +1419,14 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); //// Sub-classes can override these default implementations. //// All these methods assume arguments are already validated. - /*non-public*/ MethodHandle convertArguments(MethodType newType) { - // Override this if it can be improved. - return MethodHandleImpl.makePairwiseConvert(this, newType, 1); - } - /*non-public*/ - MethodHandle bindArgument(int pos, BasicType basicType, Object value) { - // Override this if it can be improved. - return rebind().bindArgument(pos, basicType, value); - } + abstract MethodHandle copyWith(MethodType mt, LambdaForm lf); - /*non-public*/ - MethodHandle bindReceiver(Object receiver) { - // Override this if it can be improved. - return bindArgument(0, L_TYPE, receiver); - } - - /*non-public*/ - MethodHandle dropArguments(MethodType srcType, int pos, int drops) { - // Override this if it can be improved. - return rebind().dropArguments(srcType, pos, drops); - } - - /*non-public*/ - MethodHandle permuteArguments(MethodType newType, int[] reorder) { - // Override this if it can be improved. - return rebind().permuteArguments(newType, reorder); - } - - /*non-public*/ - MethodHandle rebind() { - // Bind 'this' into a new invoker, of the known class BMH. - MethodType type2 = type(); - LambdaForm form2 = reinvokerForm(this); - // form2 = lambda (bmh, arg*) { thismh = bmh[0]; invokeBasic(thismh, arg*) } - return BoundMethodHandle.bindSingle(type2, form2, this); - } - - /*non-public*/ - MethodHandle reinvokerTarget() { - throw new InternalError("not a reinvoker MH: "+this.getClass().getName()+": "+this); - } - - /** Create a LF which simply reinvokes a target of the given basic type. - * The target MH must override {@link #reinvokerTarget} to provide the target. + /** Require this method handle to be a BMH, or else replace it with a "wrapper" BMH. + * Many transforms are implemented only for BMHs. + * @return a behaviorally equivalent BMH */ - static LambdaForm reinvokerForm(MethodHandle target) { - MethodType mtype = target.type().basicType(); - LambdaForm reinvoker = mtype.form().cachedLambdaForm(MethodTypeForm.LF_REINVOKE); - if (reinvoker != null) return reinvoker; - if (mtype.parameterSlotCount() >= MethodType.MAX_MH_ARITY) - return makeReinvokerForm(target.type(), target); // cannot cache this - reinvoker = makeReinvokerForm(mtype, null); - return mtype.form().setCachedLambdaForm(MethodTypeForm.LF_REINVOKE, reinvoker); - } - private static LambdaForm makeReinvokerForm(MethodType mtype, MethodHandle customTargetOrNull) { - boolean customized = (customTargetOrNull != null); - MethodHandle MH_invokeBasic = customized ? null : MethodHandles.basicInvoker(mtype); - final int THIS_BMH = 0; - final int ARG_BASE = 1; - final int ARG_LIMIT = ARG_BASE + mtype.parameterCount(); - int nameCursor = ARG_LIMIT; - final int NEXT_MH = customized ? -1 : nameCursor++; - final int REINVOKE = nameCursor++; - LambdaForm.Name[] names = LambdaForm.arguments(nameCursor - ARG_LIMIT, mtype.invokerType()); - Object[] targetArgs; - MethodHandle targetMH; - if (customized) { - targetArgs = Arrays.copyOfRange(names, ARG_BASE, ARG_LIMIT, Object[].class); - targetMH = customTargetOrNull; - } else { - names[NEXT_MH] = new LambdaForm.Name(NF_reinvokerTarget, names[THIS_BMH]); - targetArgs = Arrays.copyOfRange(names, THIS_BMH, ARG_LIMIT, Object[].class); - targetArgs[0] = names[NEXT_MH]; // overwrite this MH with next MH - targetMH = MethodHandles.basicInvoker(mtype); - } - names[REINVOKE] = new LambdaForm.Name(targetMH, targetArgs); - return new LambdaForm("BMH.reinvoke", ARG_LIMIT, names); - } - - private static final LambdaForm.NamedFunction NF_reinvokerTarget; - static { - try { - NF_reinvokerTarget = new LambdaForm.NamedFunction(MethodHandle.class - .getDeclaredMethod("reinvokerTarget")); - } catch (ReflectiveOperationException ex) { - throw newInternalError(ex); - } - } + abstract BoundMethodHandle rebind(); /** * Replace the old lambda form of this method handle with a new one. @@ -1470,6 +1438,7 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString()); /*non-public*/ void updateForm(LambdaForm newForm) { if (form == newForm) return; + assert(this instanceof DirectMethodHandle && this.internalMemberName().isStatic()); // ISSUE: Should we have a memory fence here? UNSAFE.putObject(this, FORM_OFFSET, newForm); this.form.prepare(); // as in MethodHandle. diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index abd8999aeaa..7b018f036cf 100644 --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -27,8 +27,10 @@ package java.lang.invoke; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.ArrayList; import java.util.Arrays; -import java.util.HashMap; +import java.util.Collections; + import sun.invoke.empty.Empty; import sun.invoke.util.ValueConversions; import sun.invoke.util.VerifyType; @@ -44,6 +46,20 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; * @author jrose */ /*non-public*/ abstract class MethodHandleImpl { + // Do not adjust this except for special platforms: + private static final int MAX_ARITY; + static { + final Object[] values = { 255 }; + AccessController.doPrivileged(new PrivilegedAction() { + @Override + public Void run() { + values[0] = Integer.getInteger(MethodHandleImpl.class.getName()+".MAX_ARITY", 255); + return null; + } + }); + MAX_ARITY = (Integer) values[0]; + } + /// Factory methods to create method handles: static void initStatics() { @@ -52,27 +68,55 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; } static MethodHandle makeArrayElementAccessor(Class arrayClass, boolean isSetter) { + if (arrayClass == Object[].class) + return (isSetter ? ArrayAccessor.OBJECT_ARRAY_SETTER : ArrayAccessor.OBJECT_ARRAY_GETTER); if (!arrayClass.isArray()) throw newIllegalArgumentException("not an array: "+arrayClass); - MethodHandle accessor = ArrayAccessor.getAccessor(arrayClass, isSetter); - MethodType srcType = accessor.type().erase(); - MethodType lambdaType = srcType.invokerType(); - Name[] names = arguments(1, lambdaType); - Name[] args = Arrays.copyOfRange(names, 1, 1 + srcType.parameterCount()); - names[names.length - 1] = new Name(accessor.asType(srcType), (Object[]) args); - LambdaForm form = new LambdaForm("getElement", lambdaType.parameterCount(), names); - MethodHandle mh = SimpleMethodHandle.make(srcType, form); - if (ArrayAccessor.needCast(arrayClass)) { - mh = mh.bindTo(arrayClass); + MethodHandle[] cache = ArrayAccessor.TYPED_ACCESSORS.get(arrayClass); + int cacheIndex = (isSetter ? ArrayAccessor.SETTER_INDEX : ArrayAccessor.GETTER_INDEX); + MethodHandle mh = cache[cacheIndex]; + if (mh != null) return mh; + mh = ArrayAccessor.getAccessor(arrayClass, isSetter); + MethodType correctType = ArrayAccessor.correctType(arrayClass, isSetter); + if (mh.type() != correctType) { + assert(mh.type().parameterType(0) == Object[].class); + assert((isSetter ? mh.type().parameterType(2) : mh.type().returnType()) == Object.class); + assert(isSetter || correctType.parameterType(0).getComponentType() == correctType.returnType()); + // safe to view non-strictly, because element type follows from array type + mh = mh.viewAsType(correctType, false); + } + mh = makeIntrinsic(mh, (isSetter ? Intrinsic.ARRAY_STORE : Intrinsic.ARRAY_LOAD)); + // Atomically update accessor cache. + synchronized(cache) { + if (cache[cacheIndex] == null) { + cache[cacheIndex] = mh; + } else { + // Throw away newly constructed accessor and use cached version. + mh = cache[cacheIndex]; + } } - mh = mh.asType(ArrayAccessor.correctType(arrayClass, isSetter)); return mh; } static final class ArrayAccessor { /// Support for array element access - static final HashMap, MethodHandle> GETTER_CACHE = new HashMap<>(); // TODO use it - static final HashMap, MethodHandle> SETTER_CACHE = new HashMap<>(); // TODO use it + static final int GETTER_INDEX = 0, SETTER_INDEX = 1, INDEX_LIMIT = 2; + static final ClassValue TYPED_ACCESSORS + = new ClassValue() { + @Override + protected MethodHandle[] computeValue(Class type) { + return new MethodHandle[INDEX_LIMIT]; + } + }; + static final MethodHandle OBJECT_ARRAY_GETTER, OBJECT_ARRAY_SETTER; + static { + MethodHandle[] cache = TYPED_ACCESSORS.get(Object[].class); + cache[GETTER_INDEX] = OBJECT_ARRAY_GETTER = makeIntrinsic(getAccessor(Object[].class, false), Intrinsic.ARRAY_LOAD); + cache[SETTER_INDEX] = OBJECT_ARRAY_SETTER = makeIntrinsic(getAccessor(Object[].class, true), Intrinsic.ARRAY_STORE); + + assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_GETTER.internalMemberName())); + assert(InvokerBytecodeGenerator.isStaticallyInvocable(ArrayAccessor.OBJECT_ARRAY_SETTER.internalMemberName())); + } static int getElementI(int[] a, int i) { return a[i]; } static long getElementJ(long[] a, int i) { return a[i]; } @@ -94,45 +138,21 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; static void setElementC(char[] a, int i, char x) { a[i] = x; } static void setElementL(Object[] a, int i, Object x) { a[i] = x; } - static Object getElementL(Class arrayClass, Object[] a, int i) { arrayClass.cast(a); return a[i]; } - static void setElementL(Class arrayClass, Object[] a, int i, Object x) { arrayClass.cast(a); a[i] = x; } - - // Weakly typed wrappers of Object[] accessors: - static Object getElementL(Object a, int i) { return getElementL((Object[])a, i); } - static void setElementL(Object a, int i, Object x) { setElementL((Object[]) a, i, x); } - static Object getElementL(Object arrayClass, Object a, int i) { return getElementL((Class) arrayClass, (Object[])a, i); } - static void setElementL(Object arrayClass, Object a, int i, Object x) { setElementL((Class) arrayClass, (Object[])a, i, x); } - - static boolean needCast(Class arrayClass) { - Class elemClass = arrayClass.getComponentType(); - return !elemClass.isPrimitive() && elemClass != Object.class; - } static String name(Class arrayClass, boolean isSetter) { Class elemClass = arrayClass.getComponentType(); - if (elemClass == null) throw new IllegalArgumentException(); + if (elemClass == null) throw newIllegalArgumentException("not an array", arrayClass); return (!isSetter ? "getElement" : "setElement") + Wrapper.basicTypeChar(elemClass); } - static final boolean USE_WEAKLY_TYPED_ARRAY_ACCESSORS = false; // FIXME: decide static MethodType type(Class arrayClass, boolean isSetter) { Class elemClass = arrayClass.getComponentType(); Class arrayArgClass = arrayClass; if (!elemClass.isPrimitive()) { arrayArgClass = Object[].class; - if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS) - arrayArgClass = Object.class; + elemClass = Object.class; } - if (!needCast(arrayClass)) { - return !isSetter ? + return !isSetter ? MethodType.methodType(elemClass, arrayArgClass, int.class) : MethodType.methodType(void.class, arrayArgClass, int.class, elemClass); - } else { - Class classArgClass = Class.class; - if (USE_WEAKLY_TYPED_ARRAY_ACCESSORS) - classArgClass = Object.class; - return !isSetter ? - MethodType.methodType(Object.class, classArgClass, arrayArgClass, int.class) : - MethodType.methodType(void.class, classArgClass, arrayArgClass, int.class, Object.class); - } } static MethodType correctType(Class arrayClass, boolean isSetter) { Class elemClass = arrayClass.getComponentType(); @@ -159,40 +179,110 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; * integral widening or narrowing, and floating point widening or narrowing. * @param srcType required call type * @param target original method handle - * @param level which strength of conversion is allowed + * @param strict if true, only asType conversions are allowed; if false, explicitCastArguments conversions allowed + * @param monobox if true, unboxing conversions are assumed to be exactly typed (Integer to int only, not long or double) * @return an adapter to the original handle with the desired new type, * or the original target if the types are already identical * or null if the adaptation cannot be made */ - static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, int level) { - assert(level >= 0 && level <= 2); + static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, + boolean strict, boolean monobox) { MethodType dstType = target.type(); assert(dstType.parameterCount() == target.type().parameterCount()); if (srcType == dstType) return target; + if (USE_LAMBDA_FORM_EDITOR) { + return makePairwiseConvertByEditor(target, srcType, strict, monobox); + } else { + return makePairwiseConvertIndirect(target, srcType, strict, monobox); + } + } - // Calculate extra arguments (temporaries) required in the names array. - // FIXME: Use an ArrayList. Some arguments require more than one conversion step. - final int INARG_COUNT = srcType.parameterCount(); - int conversions = 0; - boolean[] needConv = new boolean[1+INARG_COUNT]; - for (int i = 0; i <= INARG_COUNT; i++) { - Class src = (i == INARG_COUNT) ? dstType.returnType() : srcType.parameterType(i); - Class dst = (i == INARG_COUNT) ? srcType.returnType() : dstType.parameterType(i); - if (!VerifyType.isNullConversion(src, dst) || - level <= 1 && dst.isInterface() && !dst.isAssignableFrom(src)) { - needConv[i] = true; - conversions++; + private static int countNonNull(Object[] array) { + int count = 0; + for (Object x : array) { + if (x != null) ++count; + } + return count; + } + + static MethodHandle makePairwiseConvertByEditor(MethodHandle target, MethodType srcType, + boolean strict, boolean monobox) { + Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox); + int convCount = countNonNull(convSpecs); + if (convCount == 0) + return target.viewAsType(srcType, strict); + MethodType basicSrcType = srcType.basicType(); + MethodType midType = target.type().basicType(); + BoundMethodHandle mh = target.rebind(); + // FIXME: Reduce number of bindings when there is more than one Class conversion. + // FIXME: Reduce number of bindings when there are repeated conversions. + for (int i = 0; i < convSpecs.length-1; i++) { + Object convSpec = convSpecs[i]; + if (convSpec == null) continue; + MethodHandle fn; + if (convSpec instanceof Class) { + fn = Lazy.MH_castReference.bindTo(convSpec); + } else { + fn = (MethodHandle) convSpec; + } + Class newType = basicSrcType.parameterType(i); + if (--convCount == 0) + midType = srcType; + else + midType = midType.changeParameterType(i, newType); + LambdaForm form2 = mh.editor().filterArgumentForm(1+i, BasicType.basicType(newType)); + mh = mh.copyWithExtendL(midType, form2, fn); + mh = mh.rebind(); + } + Object convSpec = convSpecs[convSpecs.length-1]; + if (convSpec != null) { + MethodHandle fn; + if (convSpec instanceof Class) { + if (convSpec == void.class) + fn = null; + else + fn = Lazy.MH_castReference.bindTo(convSpec); + } else { + fn = (MethodHandle) convSpec; + } + Class newType = basicSrcType.returnType(); + assert(--convCount == 0); + midType = srcType; + if (fn != null) { + mh = mh.rebind(); // rebind if too complex + LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), false); + mh = mh.copyWithExtendL(midType, form2, fn); + } else { + LambdaForm form2 = mh.editor().filterReturnForm(BasicType.basicType(newType), true); + mh = mh.copyWith(midType, form2); } } - boolean retConv = needConv[INARG_COUNT]; + assert(convCount == 0); + assert(mh.type().equals(srcType)); + return mh; + } + + static MethodHandle makePairwiseConvertIndirect(MethodHandle target, MethodType srcType, + boolean strict, boolean monobox) { + // Calculate extra arguments (temporaries) required in the names array. + Object[] convSpecs = computeValueConversions(srcType, target.type(), strict, monobox); + final int INARG_COUNT = srcType.parameterCount(); + int convCount = countNonNull(convSpecs); + boolean retConv = (convSpecs[INARG_COUNT] != null); + boolean retVoid = srcType.returnType() == void.class; + if (retConv && retVoid) { + convCount -= 1; + retConv = false; + } final int IN_MH = 0; final int INARG_BASE = 1; final int INARG_LIMIT = INARG_BASE + INARG_COUNT; - final int NAME_LIMIT = INARG_LIMIT + conversions + 1; + final int NAME_LIMIT = INARG_LIMIT + convCount + 1; final int RETURN_CONV = (!retConv ? -1 : NAME_LIMIT - 1); final int OUT_CALL = (!retConv ? NAME_LIMIT : RETURN_CONV) - 1; + final int RESULT = (retVoid ? -1 : NAME_LIMIT - 1); // Now build a LambdaForm. MethodType lambdaType = srcType.basicType().invokerType(); @@ -204,59 +294,21 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; int nameCursor = INARG_LIMIT; for (int i = 0; i < INARG_COUNT; i++) { - Class src = srcType.parameterType(i); - Class dst = dstType.parameterType(i); - - if (!needConv[i]) { + Object convSpec = convSpecs[i]; + if (convSpec == null) { // do nothing: difference is trivial outArgs[OUTARG_BASE + i] = names[INARG_BASE + i]; continue; } - // Tricky case analysis follows. - MethodHandle fn = null; - if (src.isPrimitive()) { - if (dst.isPrimitive()) { - fn = ValueConversions.convertPrimitive(src, dst); - } else { - Wrapper w = Wrapper.forPrimitiveType(src); - MethodHandle boxMethod = ValueConversions.box(w); - if (dst == w.wrapperType()) - fn = boxMethod; - else - fn = boxMethod.asType(MethodType.methodType(dst, src)); - } + Name conv; + if (convSpec instanceof Class) { + Class convClass = (Class) convSpec; + conv = new Name(Lazy.MH_castReference, convClass, names[INARG_BASE + i]); } else { - if (dst.isPrimitive()) { - // Caller has boxed a primitive. Unbox it for the target. - Wrapper w = Wrapper.forPrimitiveType(dst); - if (level == 0 || VerifyType.isNullConversion(src, w.wrapperType())) { - fn = ValueConversions.unbox(dst); - } else if (src == Object.class || !Wrapper.isWrapperType(src)) { - // Examples: Object->int, Number->int, Comparable->int; Byte->int, Character->int - // must include additional conversions - // src must be examined at runtime, to detect Byte, Character, etc. - MethodHandle unboxMethod = (level == 1 - ? ValueConversions.unbox(dst) - : ValueConversions.unboxCast(dst)); - fn = unboxMethod; - } else { - // Example: Byte->int - // Do this by reformulating the problem to Byte->byte. - Class srcPrim = Wrapper.forWrapperType(src).primitiveType(); - MethodHandle unbox = ValueConversions.unbox(srcPrim); - // Compose the two conversions. FIXME: should make two Names for this job - fn = unbox.asType(MethodType.methodType(dst, src)); - } - } else { - // Simple reference conversion. - // Note: Do not check for a class hierarchy relation - // between src and dst. In all cases a 'null' argument - // will pass the cast conversion. - fn = ValueConversions.cast(dst, Lazy.MH_castReference); - } + MethodHandle fn = (MethodHandle) convSpec; + conv = new Name(fn, names[INARG_BASE + i]); } - Name conv = new Name(fn, names[INARG_BASE + i]); assert(names[nameCursor] == null); names[nameCursor++] = conv; assert(outArgs[OUTARG_BASE + i] == null); @@ -267,29 +319,29 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; assert(nameCursor == OUT_CALL); names[OUT_CALL] = new Name(target, outArgs); - if (RETURN_CONV < 0) { + Object convSpec = convSpecs[INARG_COUNT]; + if (!retConv) { assert(OUT_CALL == names.length-1); } else { - Class needReturn = srcType.returnType(); - Class haveReturn = dstType.returnType(); - MethodHandle fn; - Object[] arg = { names[OUT_CALL] }; - if (haveReturn == void.class) { - // synthesize a zero value for the given void - Object zero = Wrapper.forBasicType(needReturn).zero(); - fn = MethodHandles.constant(needReturn, zero); - arg = new Object[0]; // don't pass names[OUT_CALL] to conversion + Name conv; + if (convSpec == void.class) { + conv = new Name(LambdaForm.constantZero(BasicType.basicType(srcType.returnType()))); + } else if (convSpec instanceof Class) { + Class convClass = (Class) convSpec; + conv = new Name(Lazy.MH_castReference, convClass, names[OUT_CALL]); } else { - MethodHandle identity = MethodHandles.identity(needReturn); - MethodType needConversion = identity.type().changeParameterType(0, haveReturn); - fn = makePairwiseConvert(identity, needConversion, level); + MethodHandle fn = (MethodHandle) convSpec; + if (fn.type().parameterCount() == 0) + conv = new Name(fn); // don't pass retval to void conversion + else + conv = new Name(fn, names[OUT_CALL]); } assert(names[RETURN_CONV] == null); - names[RETURN_CONV] = new Name(fn, arg); + names[RETURN_CONV] = conv; assert(RETURN_CONV == names.length-1); } - LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names); + LambdaForm form = new LambdaForm("convert", lambdaType.parameterCount(), names, RESULT); return SimpleMethodHandle.make(srcType, form); } @@ -312,12 +364,79 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); } - static MethodHandle makeReferenceIdentity(Class refType) { - MethodType lambdaType = MethodType.genericMethodType(1).invokerType(); - Name[] names = arguments(1, lambdaType); - names[names.length - 1] = new Name(ValueConversions.identity(), names[1]); - LambdaForm form = new LambdaForm("identity", lambdaType.parameterCount(), names); - return SimpleMethodHandle.make(MethodType.methodType(refType, refType), form); + static Object[] computeValueConversions(MethodType srcType, MethodType dstType, + boolean strict, boolean monobox) { + final int INARG_COUNT = srcType.parameterCount(); + Object[] convSpecs = new Object[INARG_COUNT+1]; + for (int i = 0; i <= INARG_COUNT; i++) { + boolean isRet = (i == INARG_COUNT); + Class src = isRet ? dstType.returnType() : srcType.parameterType(i); + Class dst = isRet ? srcType.returnType() : dstType.parameterType(i); + if (!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)) { + convSpecs[i] = valueConversion(src, dst, strict, monobox); + } + } + return convSpecs; + } + static MethodHandle makePairwiseConvert(MethodHandle target, MethodType srcType, + boolean strict) { + return makePairwiseConvert(target, srcType, strict, /*monobox=*/ false); + } + + /** + * Find a conversion function from the given source to the given destination. + * This conversion function will be used as a LF NamedFunction. + * Return a Class object if a simple cast is needed. + * Return void.class if void is involved. + */ + static Object valueConversion(Class src, Class dst, boolean strict, boolean monobox) { + assert(!VerifyType.isNullConversion(src, dst, /*keepInterfaces=*/ strict)); // caller responsibility + if (dst == void.class) + return dst; + MethodHandle fn; + if (src.isPrimitive()) { + if (src == void.class) { + return void.class; // caller must recognize this specially + } else if (dst.isPrimitive()) { + // Examples: int->byte, byte->int, boolean->int (!strict) + fn = ValueConversions.convertPrimitive(src, dst); + } else { + // Examples: int->Integer, boolean->Object, float->Number + Wrapper wsrc = Wrapper.forPrimitiveType(src); + fn = ValueConversions.boxExact(wsrc); + assert(fn.type().parameterType(0) == wsrc.primitiveType()); + assert(fn.type().returnType() == wsrc.wrapperType()); + if (!VerifyType.isNullConversion(wsrc.wrapperType(), dst, strict)) { + // Corner case, such as int->Long, which will probably fail. + MethodType mt = MethodType.methodType(dst, src); + if (strict) + fn = fn.asType(mt); + else + fn = MethodHandleImpl.makePairwiseConvert(fn, mt, /*strict=*/ false); + } + } + } else if (dst.isPrimitive()) { + Wrapper wdst = Wrapper.forPrimitiveType(dst); + if (monobox || src == wdst.wrapperType()) { + // Use a strongly-typed unboxer, if possible. + fn = ValueConversions.unboxExact(wdst, strict); + } else { + // Examples: Object->int, Number->int, Comparable->int, Byte->int + // must include additional conversions + // src must be examined at runtime, to detect Byte, Character, etc. + fn = (strict + ? ValueConversions.unboxWiden(wdst) + : ValueConversions.unboxCast(wdst)); + } + } else { + // Simple reference conversion. + // Note: Do not check for a class hierarchy relation + // between src and dst. In all cases a 'null' argument + // will pass the cast conversion. + return dst; + } + assert(fn.type().parameterCount() <= 1) : "pc"+Arrays.asList(src.getSimpleName(), dst.getSimpleName(), fn); + return fn; } static MethodHandle makeVarargsCollector(MethodHandle target, Class arrayType) { @@ -326,33 +445,45 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; if (type.parameterType(last) != arrayType) target = target.asType(type.changeParameterType(last, arrayType)); target = target.asFixedArity(); // make sure this attribute is turned off - return new AsVarargsCollector(target, target.type(), arrayType); + return new AsVarargsCollector(target, arrayType); } - static class AsVarargsCollector extends MethodHandle { + private static final class AsVarargsCollector extends DelegatingMethodHandle { private final MethodHandle target; private final Class arrayType; - private /*@Stable*/ MethodHandle asCollectorCache; + private @Stable MethodHandle asCollectorCache; - AsVarargsCollector(MethodHandle target, MethodType type, Class arrayType) { - super(type, reinvokerForm(target)); + AsVarargsCollector(MethodHandle target, Class arrayType) { + this(target.type(), target, arrayType); + } + AsVarargsCollector(MethodType type, MethodHandle target, Class arrayType) { + super(type, target); this.target = target; this.arrayType = arrayType; this.asCollectorCache = target.asCollector(arrayType, 0); } - @Override MethodHandle reinvokerTarget() { return target; } - @Override public boolean isVarargsCollector() { return true; } + @Override + protected MethodHandle getTarget() { + return target; + } + @Override public MethodHandle asFixedArity() { return target; } + @Override + MethodHandle setVarargs(MemberName member) { + if (member.isVarargs()) return this; + return asFixedArity(); + } + @Override public MethodHandle asTypeUncached(MethodType newType) { MethodType type = this.type(); @@ -381,54 +512,15 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; } @Override - MethodHandle setVarargs(MemberName member) { - if (member.isVarargs()) return this; - return asFixedArity(); - } - - @Override - MethodHandle viewAsType(MethodType newType) { - if (newType.lastParameterType() != type().lastParameterType()) - throw new InternalError(); - MethodHandle newTarget = asFixedArity().viewAsType(newType); - // put back the varargs bit: - return new AsVarargsCollector(newTarget, newType, arrayType); - } - - @Override - MemberName internalMemberName() { - return asFixedArity().internalMemberName(); - } - @Override - Class internalCallerClass() { - return asFixedArity().internalCallerClass(); - } - - /*non-public*/ - @Override - boolean isInvokeSpecial() { - return asFixedArity().isInvokeSpecial(); - } - - - @Override - MethodHandle bindArgument(int pos, BasicType basicType, Object value) { - return asFixedArity().bindArgument(pos, basicType, value); - } - - @Override - MethodHandle bindReceiver(Object receiver) { - return asFixedArity().bindReceiver(receiver); - } - - @Override - MethodHandle dropArguments(MethodType srcType, int pos, int drops) { - return asFixedArity().dropArguments(srcType, pos, drops); - } - - @Override - MethodHandle permuteArguments(MethodType newType, int[] reorder) { - return asFixedArity().permuteArguments(newType, reorder); + boolean viewAsTypeChecks(MethodType newType, boolean strict) { + super.viewAsTypeChecks(newType, true); + if (strict) return true; + // extra assertion for non-strict checks: + assert (type().lastParameterType().getComponentType() + .isAssignableFrom( + newType.lastParameterType().getComponentType())) + : Arrays.asList(this, newType); + return true; } } @@ -499,32 +591,46 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; * Pre-initialized NamedFunctions for bootstrapping purposes. * Factored in an inner class to delay initialization until first usage. */ - private static class Lazy { + static class Lazy { private static final Class MHI = MethodHandleImpl.class; static final NamedFunction NF_checkSpreadArgument; static final NamedFunction NF_guardWithCatch; - static final NamedFunction NF_selectAlternative; static final NamedFunction NF_throwException; static final MethodHandle MH_castReference; + static final MethodHandle MH_selectAlternative; + static final MethodHandle MH_copyAsPrimitiveArray; + static final MethodHandle MH_fillNewTypedArray; + static final MethodHandle MH_fillNewArray; + static final MethodHandle MH_arrayIdentity; static { try { NF_checkSpreadArgument = new NamedFunction(MHI.getDeclaredMethod("checkSpreadArgument", Object.class, int.class)); NF_guardWithCatch = new NamedFunction(MHI.getDeclaredMethod("guardWithCatch", MethodHandle.class, Class.class, MethodHandle.class, Object[].class)); - NF_selectAlternative = new NamedFunction(MHI.getDeclaredMethod("selectAlternative", boolean.class, MethodHandle.class, - MethodHandle.class)); NF_throwException = new NamedFunction(MHI.getDeclaredMethod("throwException", Throwable.class)); NF_checkSpreadArgument.resolve(); NF_guardWithCatch.resolve(); - NF_selectAlternative.resolve(); NF_throwException.resolve(); - MethodType mt = MethodType.methodType(Object.class, Class.class, Object.class); - MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", mt); + MH_castReference = IMPL_LOOKUP.findStatic(MHI, "castReference", + MethodType.methodType(Object.class, Class.class, Object.class)); + MH_copyAsPrimitiveArray = IMPL_LOOKUP.findStatic(MHI, "copyAsPrimitiveArray", + MethodType.methodType(Object.class, Wrapper.class, Object[].class)); + MH_arrayIdentity = IMPL_LOOKUP.findStatic(MHI, "identity", + MethodType.methodType(Object[].class, Object[].class)); + MH_fillNewArray = IMPL_LOOKUP.findStatic(MHI, "fillNewArray", + MethodType.methodType(Object[].class, Integer.class, Object[].class)); + MH_fillNewTypedArray = IMPL_LOOKUP.findStatic(MHI, "fillNewTypedArray", + MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class)); + + MH_selectAlternative = makeIntrinsic( + IMPL_LOOKUP.findStatic(MHI, "selectAlternative", + MethodType.methodType(MethodHandle.class, boolean.class, MethodHandle.class, MethodHandle.class)), + Intrinsic.SELECT_ALTERNATIVE); } catch (ReflectiveOperationException ex) { throw newInternalError(ex); } @@ -595,33 +701,70 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; MethodHandle makeGuardWithTest(MethodHandle test, MethodHandle target, MethodHandle fallback) { - MethodType basicType = target.type().basicType(); - MethodHandle invokeBasic = MethodHandles.basicInvoker(basicType); - int arity = basicType.parameterCount(); - int extraNames = 3; - MethodType lambdaType = basicType.invokerType(); - Name[] names = arguments(extraNames, lambdaType); + MethodType type = target.type(); + assert(test.type().equals(type.changeReturnType(boolean.class)) && fallback.type().equals(type)); + MethodType basicType = type.basicType(); + LambdaForm form = makeGuardWithTestForm(basicType); + BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL(); + BoundMethodHandle mh; + try { + mh = (BoundMethodHandle) + data.constructor().invokeBasic(type, form, + (Object) test, (Object) target, (Object) fallback); + } catch (Throwable ex) { + throw uncaughtException(ex); + } + assert(mh.type() == type); + return mh; + } - Object[] testArgs = Arrays.copyOfRange(names, 1, 1 + arity, Object[].class); - Object[] targetArgs = Arrays.copyOfRange(names, 0, 1 + arity, Object[].class); + static + LambdaForm makeGuardWithTestForm(MethodType basicType) { + LambdaForm lform = basicType.form().cachedLambdaForm(MethodTypeForm.LF_GWT); + if (lform != null) return lform; + final int THIS_MH = 0; // the BMH_LLL + final int ARG_BASE = 1; // start of incoming arguments + final int ARG_LIMIT = ARG_BASE + basicType.parameterCount(); + int nameCursor = ARG_LIMIT; + final int GET_TEST = nameCursor++; + final int GET_TARGET = nameCursor++; + final int GET_FALLBACK = nameCursor++; + final int CALL_TEST = nameCursor++; + final int SELECT_ALT = nameCursor++; + final int CALL_TARGET = nameCursor++; + assert(CALL_TARGET == SELECT_ALT+1); // must be true to trigger IBG.emitSelectAlternative + + MethodType lambdaType = basicType.invokerType(); + Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType); + + BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLL(); + names[THIS_MH] = names[THIS_MH].withConstraint(data); + names[GET_TEST] = new Name(data.getterFunction(0), names[THIS_MH]); + names[GET_TARGET] = new Name(data.getterFunction(1), names[THIS_MH]); + names[GET_FALLBACK] = new Name(data.getterFunction(2), names[THIS_MH]); + + Object[] invokeArgs = Arrays.copyOfRange(names, 0, ARG_LIMIT, Object[].class); // call test - names[arity + 1] = new Name(test, testArgs); + MethodType testType = basicType.changeReturnType(boolean.class).basicType(); + invokeArgs[0] = names[GET_TEST]; + names[CALL_TEST] = new Name(testType, invokeArgs); // call selectAlternative - Object[] selectArgs = { names[arity + 1], target, fallback }; - names[arity + 2] = new Name(Lazy.NF_selectAlternative, selectArgs); - targetArgs[0] = names[arity + 2]; + names[SELECT_ALT] = new Name(Lazy.MH_selectAlternative, names[CALL_TEST], + names[GET_TARGET], names[GET_FALLBACK]); // call target or fallback - names[arity + 3] = new Name(new NamedFunction(invokeBasic), targetArgs); + invokeArgs[0] = names[SELECT_ALT]; + names[CALL_TARGET] = new Name(basicType, invokeArgs); - LambdaForm form = new LambdaForm("guard", lambdaType.parameterCount(), names); - return SimpleMethodHandle.make(target.type(), form); + lform = new LambdaForm("guard", lambdaType.parameterCount(), names); + + return basicType.form().setCachedLambdaForm(MethodTypeForm.LF_GWT, lform); } /** - * The LambaForm shape for catchException combinator is the following: + * The LambdaForm shape for catchException combinator is the following: *

    {@code
          *  guardWithCatch=Lambda(a0:L,a1:L,a2:L)=>{
          *    t3:L=BoundMethodHandle$Species_LLLLL.argL0(a0:L);
    @@ -665,6 +808,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
             Name[] names = arguments(nameCursor - ARG_LIMIT, lambdaType);
     
             BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
    +        names[THIS_MH]          = names[THIS_MH].withConstraint(data);
             names[GET_TARGET]       = new Name(data.getterFunction(0), names[THIS_MH]);
             names[GET_CLASS]        = new Name(data.getterFunction(1), names[THIS_MH]);
             names[GET_CATCHER]      = new Name(data.getterFunction(2), names[THIS_MH]);
    @@ -679,7 +823,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
             Object[] args = new Object[invokeBasic.type().parameterCount()];
             args[0] = names[GET_COLLECT_ARGS];
             System.arraycopy(names, ARG_BASE, args, 1, ARG_LIMIT-ARG_BASE);
    -        names[BOXED_ARGS] = new Name(new NamedFunction(invokeBasic), args);
    +        names[BOXED_ARGS] = new Name(makeIntrinsic(invokeBasic, Intrinsic.GUARD_WITH_CATCH), args);
     
             // t_{i+1}:L=MethodHandleImpl.guardWithCatch(target:L,exType:L,catcher:L,t_{i}:L);
             Object[] gwcArgs = new Object[] {names[GET_TARGET], names[GET_CLASS], names[GET_CATCHER], names[BOXED_ARGS]};
    @@ -688,7 +832,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
             // t_{i+2}:I=MethodHandle.invokeBasic(unbox:L,t_{i+1}:L);
             MethodHandle invokeBasicUnbox = MethodHandles.basicInvoker(MethodType.methodType(basicType.rtype(), Object.class));
             Object[] unboxArgs  = new Object[] {names[GET_UNBOX_RESULT], names[TRY_CATCH]};
    -        names[UNBOX_RESULT] = new Name(new NamedFunction(invokeBasicUnbox), unboxArgs);
    +        names[UNBOX_RESULT] = new Name(invokeBasicUnbox, unboxArgs);
     
             lform = new LambdaForm("guardWithCatch", lambdaType.parameterCount(), names);
     
    @@ -702,25 +846,30 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
             MethodType type = target.type();
             LambdaForm form = makeGuardWithCatchForm(type.basicType());
     
    -        // Prepare auxiliary method handles used during LambdaForm interpreation.
    +        // Prepare auxiliary method handles used during LambdaForm interpretation.
             // Box arguments and wrap them into Object[]: ValueConversions.array().
             MethodType varargsType = type.changeReturnType(Object[].class);
    -        MethodHandle collectArgs = ValueConversions.varargsArray(type.parameterCount())
    -                                                   .asType(varargsType);
    +        MethodHandle collectArgs = varargsArray(type.parameterCount()).asType(varargsType);
             // Result unboxing: ValueConversions.unbox() OR ValueConversions.identity() OR ValueConversions.ignore().
             MethodHandle unboxResult;
    -        if (type.returnType().isPrimitive()) {
    -            unboxResult = ValueConversions.unbox(type.returnType());
    +        Class rtype = type.returnType();
    +        if (rtype.isPrimitive()) {
    +            if (rtype == void.class) {
    +                unboxResult = ValueConversions.ignore();
    +            } else {
    +                Wrapper w = Wrapper.forPrimitiveType(type.returnType());
    +                unboxResult = ValueConversions.unboxExact(w);
    +            }
             } else {
    -            unboxResult = ValueConversions.identity();
    +            unboxResult = MethodHandles.identity(Object.class);
             }
     
             BoundMethodHandle.SpeciesData data = BoundMethodHandle.speciesData_LLLLL();
             BoundMethodHandle mh;
             try {
                 mh = (BoundMethodHandle)
    -                    data.constructor[0].invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
    -                                                    (Object) collectArgs, (Object) unboxResult);
    +                    data.constructor().invokeBasic(type, form, (Object) target, (Object) exType, (Object) catcher,
    +                                                   (Object) collectArgs, (Object) unboxResult);
             } catch (Throwable ex) {
                 throw uncaughtException(ex);
             }
    @@ -758,9 +907,11 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
             assert(Throwable.class.isAssignableFrom(type.parameterType(0)));
             int arity = type.parameterCount();
             if (arity > 1) {
    -            return throwException(type.dropParameterTypes(1, arity)).dropArguments(type, 1, arity-1);
    +            MethodHandle mh = throwException(type.dropParameterTypes(1, arity));
    +            mh = MethodHandles.dropArguments(mh, 1, type.parameterList().subList(1, arity));
    +            return mh;
             }
    -        return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, 2);
    +        return makePairwiseConvert(Lazy.NF_throwException.resolvedHandle(), type, false, true);
         }
     
         static  Empty throwException(T t) throws T { throw t; }
    @@ -782,7 +933,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
             mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke MethodHandle"));
             if (!method.getInvocationType().equals(mh.type()))
                 throw new InternalError(method.toString());
    -        mh = mh.withInternalMemberName(method);
    +        mh = mh.withInternalMemberName(method, false);
             mh = mh.asVarargsCollector(Object[].class);
             assert(method.isVarargs());
             FAKE_METHOD_HANDLE_INVOKE[idx] = mh;
    @@ -819,7 +970,7 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
                 MethodHandle vamh = prepareForInvoker(mh);
                 // Cache the result of makeInjectedInvoker once per argument class.
                 MethodHandle bccInvoker = CV_makeInjectedInvoker.get(hostClass);
    -            return restoreToType(bccInvoker.bindTo(vamh), mh.type(), mh.internalMemberName(), hostClass);
    +            return restoreToType(bccInvoker.bindTo(vamh), mh, hostClass);
             }
     
             private static MethodHandle makeInjectedInvoker(Class hostClass) {
    @@ -874,12 +1025,14 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
             }
     
             // Undo the adapter effect of prepareForInvoker:
    -        private static MethodHandle restoreToType(MethodHandle vamh, MethodType type,
    -                                                  MemberName member,
    +        private static MethodHandle restoreToType(MethodHandle vamh,
    +                                                  MethodHandle original,
                                                       Class hostClass) {
    +            MethodType type = original.type();
                 MethodHandle mh = vamh.asCollector(Object[].class, type.parameterCount());
    +            MemberName member = original.internalMemberName();
                 mh = mh.asType(type);
    -            mh = new WrappedMember(mh, type, member, hostClass);
    +            mh = new WrappedMember(mh, type, member, original.isInvokeSpecial(), hostClass);
                 return mh;
             }
     
    @@ -945,28 +1098,22 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
     
     
         /** This subclass allows a wrapped method handle to be re-associated with an arbitrary member name. */
    -    static class WrappedMember extends MethodHandle {
    +    private static final class WrappedMember extends DelegatingMethodHandle {
             private final MethodHandle target;
             private final MemberName member;
             private final Class callerClass;
    +        private final boolean isInvokeSpecial;
     
    -        private WrappedMember(MethodHandle target, MethodType type, MemberName member, Class callerClass) {
    -            super(type, reinvokerForm(target));
    +        private WrappedMember(MethodHandle target, MethodType type,
    +                              MemberName member, boolean isInvokeSpecial,
    +                              Class callerClass) {
    +            super(type, target);
                 this.target = target;
                 this.member = member;
                 this.callerClass = callerClass;
    +            this.isInvokeSpecial = isInvokeSpecial;
             }
     
    -        @Override
    -        MethodHandle reinvokerTarget() {
    -            return target;
    -        }
    -        @Override
    -        public MethodHandle asTypeUncached(MethodType newType) {
    -            // This MH is an alias for target, except for the MemberName
    -            // Drop the MemberName if there is any conversion.
    -            return asTypeCache = target.asType(newType);
    -        }
             @Override
             MemberName internalMemberName() {
                 return member;
    @@ -977,18 +1124,367 @@ import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP;
             }
             @Override
             boolean isInvokeSpecial() {
    -            return target.isInvokeSpecial();
    +            return isInvokeSpecial;
             }
             @Override
    -        MethodHandle viewAsType(MethodType newType) {
    -            return new WrappedMember(target, newType, member, callerClass);
    +        protected MethodHandle getTarget() {
    +            return target;
    +        }
    +        @Override
    +        public MethodHandle asTypeUncached(MethodType newType) {
    +            // This MH is an alias for target, except for the MemberName
    +            // Drop the MemberName if there is any conversion.
    +            return asTypeCache = target.asType(newType);
             }
         }
     
    -    static MethodHandle makeWrappedMember(MethodHandle target, MemberName member) {
    -        if (member.equals(target.internalMemberName()))
    +    static MethodHandle makeWrappedMember(MethodHandle target, MemberName member, boolean isInvokeSpecial) {
    +        if (member.equals(target.internalMemberName()) && isInvokeSpecial == target.isInvokeSpecial())
                 return target;
    -        return new WrappedMember(target, target.type(), member, null);
    +        return new WrappedMember(target, target.type(), member, isInvokeSpecial, null);
         }
     
    +    /** Intrinsic IDs */
    +    /*non-public*/
    +    enum Intrinsic {
    +        SELECT_ALTERNATIVE,
    +        GUARD_WITH_CATCH,
    +        NEW_ARRAY,
    +        ARRAY_LOAD,
    +        ARRAY_STORE,
    +        IDENTITY,
    +        ZERO,
    +        NONE // no intrinsic associated
    +    }
    +
    +    /** Mark arbitrary method handle as intrinsic.
    +     * InvokerBytecodeGenerator uses this info to produce more efficient bytecode shape. */
    +    private static final class IntrinsicMethodHandle extends DelegatingMethodHandle {
    +        private final MethodHandle target;
    +        private final Intrinsic intrinsicName;
    +
    +        IntrinsicMethodHandle(MethodHandle target, Intrinsic intrinsicName) {
    +            super(target.type(), target);
    +            this.target = target;
    +            this.intrinsicName = intrinsicName;
    +        }
    +
    +        @Override
    +        protected MethodHandle getTarget() {
    +            return target;
    +        }
    +
    +        @Override
    +        Intrinsic intrinsicName() {
    +            return intrinsicName;
    +        }
    +
    +        @Override
    +        public MethodHandle asTypeUncached(MethodType newType) {
    +            // This MH is an alias for target, except for the intrinsic name
    +            // Drop the name if there is any conversion.
    +            return asTypeCache = target.asType(newType);
    +        }
    +
    +        @Override
    +        String internalProperties() {
    +            return super.internalProperties() +
    +                    "\n& Intrinsic="+intrinsicName;
    +        }
    +
    +        @Override
    +        public MethodHandle asCollector(Class arrayType, int arrayLength) {
    +            if (intrinsicName == Intrinsic.IDENTITY) {
    +                MethodType resultType = type().asCollectorType(arrayType, arrayLength);
    +                MethodHandle newArray = MethodHandleImpl.varargsArray(arrayType, arrayLength);
    +                return newArray.asType(resultType);
    +            }
    +            return super.asCollector(arrayType, arrayLength);
    +        }
    +    }
    +
    +    static MethodHandle makeIntrinsic(MethodHandle target, Intrinsic intrinsicName) {
    +        if (intrinsicName == target.intrinsicName())
    +            return target;
    +        return new IntrinsicMethodHandle(target, intrinsicName);
    +    }
    +
    +    static MethodHandle makeIntrinsic(MethodType type, LambdaForm form, Intrinsic intrinsicName) {
    +        return new IntrinsicMethodHandle(SimpleMethodHandle.make(type, form), intrinsicName);
    +    }
    +
    +    /// Collection of multiple arguments.
    +
    +    private static MethodHandle findCollector(String name, int nargs, Class rtype, Class... ptypes) {
    +        MethodType type = MethodType.genericMethodType(nargs)
    +                .changeReturnType(rtype)
    +                .insertParameterTypes(0, ptypes);
    +        try {
    +            return IMPL_LOOKUP.findStatic(MethodHandleImpl.class, name, type);
    +        } catch (ReflectiveOperationException ex) {
    +            return null;
    +        }
    +    }
    +
    +    private static final Object[] NO_ARGS_ARRAY = {};
    +    private static Object[] makeArray(Object... args) { return args; }
    +    private static Object[] array() { return NO_ARGS_ARRAY; }
    +    private static Object[] array(Object a0)
    +                { return makeArray(a0); }
    +    private static Object[] array(Object a0, Object a1)
    +                { return makeArray(a0, a1); }
    +    private static Object[] array(Object a0, Object a1, Object a2)
    +                { return makeArray(a0, a1, a2); }
    +    private static Object[] array(Object a0, Object a1, Object a2, Object a3)
    +                { return makeArray(a0, a1, a2, a3); }
    +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4)
    +                { return makeArray(a0, a1, a2, a3, a4); }
    +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4, Object a5)
    +                { return makeArray(a0, a1, a2, a3, a4, a5); }
    +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4, Object a5, Object a6)
    +                { return makeArray(a0, a1, a2, a3, a4, a5, a6); }
    +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4, Object a5, Object a6, Object a7)
    +                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); }
    +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4, Object a5, Object a6, Object a7,
    +                                  Object a8)
    +                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); }
    +    private static Object[] array(Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4, Object a5, Object a6, Object a7,
    +                                  Object a8, Object a9)
    +                { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); }
    +    private static MethodHandle[] makeArrays() {
    +        ArrayList mhs = new ArrayList<>();
    +        for (;;) {
    +            MethodHandle mh = findCollector("array", mhs.size(), Object[].class);
    +            if (mh == null)  break;
    +            mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
    +            mhs.add(mh);
    +        }
    +        assert(mhs.size() == 11);  // current number of methods
    +        return mhs.toArray(new MethodHandle[MAX_ARITY+1]);
    +    }
    +    private static final MethodHandle[] ARRAYS = makeArrays();
    +
    +    // filling versions of the above:
    +    // using Integer len instead of int len and no varargs to avoid bootstrapping problems
    +    private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) {
    +        Object[] a = new Object[len];
    +        fillWithArguments(a, 0, args);
    +        return a;
    +    }
    +    private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) {
    +        Object[] a = Arrays.copyOf(example, len);
    +        assert(a.getClass() != Object[].class);
    +        fillWithArguments(a, 0, args);
    +        return a;
    +    }
    +    private static void fillWithArguments(Object[] a, int pos, Object... args) {
    +        System.arraycopy(args, 0, a, pos, args.length);
    +    }
    +    // using Integer pos instead of int pos to avoid bootstrapping problems
    +    private static Object[] fillArray(Integer pos, Object[] a, Object a0)
    +                { fillWithArguments(a, pos, a0); return a; }
    +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1)
    +                { fillWithArguments(a, pos, a0, a1); return a; }
    +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2)
    +                { fillWithArguments(a, pos, a0, a1, a2); return a; }
    +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3)
    +                { fillWithArguments(a, pos, a0, a1, a2, a3); return a; }
    +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4)
    +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; }
    +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4, Object a5)
    +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; }
    +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4, Object a5, Object a6)
    +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; }
    +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4, Object a5, Object a6, Object a7)
    +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; }
    +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4, Object a5, Object a6, Object a7,
    +                                  Object a8)
    +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; }
    +    private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3,
    +                                  Object a4, Object a5, Object a6, Object a7,
    +                                  Object a8, Object a9)
    +                { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; }
    +    private static MethodHandle[] makeFillArrays() {
    +        ArrayList mhs = new ArrayList<>();
    +        mhs.add(null);  // there is no empty fill; at least a0 is required
    +        for (;;) {
    +            MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class);
    +            if (mh == null)  break;
    +            mhs.add(mh);
    +        }
    +        assert(mhs.size() == 11);  // current number of methods
    +        return mhs.toArray(new MethodHandle[0]);
    +    }
    +    private static final MethodHandle[] FILL_ARRAYS = makeFillArrays();
    +
    +    private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) {
    +        Object a = w.makeArray(boxes.length);
    +        w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length);
    +        return a;
    +    }
    +
    +    /** Return a method handle that takes the indicated number of Object
    +     *  arguments and returns an Object array of them, as if for varargs.
    +     */
    +    static MethodHandle varargsArray(int nargs) {
    +        MethodHandle mh = ARRAYS[nargs];
    +        if (mh != null)  return mh;
    +        mh = findCollector("array", nargs, Object[].class);
    +        if (mh != null)  mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
    +        if (mh != null)  return ARRAYS[nargs] = mh;
    +        mh = buildVarargsArray(Lazy.MH_fillNewArray, Lazy.MH_arrayIdentity, nargs);
    +        assert(assertCorrectArity(mh, nargs));
    +        mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
    +        return ARRAYS[nargs] = mh;
    +    }
    +
    +    private static boolean assertCorrectArity(MethodHandle mh, int arity) {
    +        assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh;
    +        return true;
    +    }
    +
    +    // Array identity function (used as Lazy.MH_arrayIdentity).
    +    static  T[] identity(T[] x) {
    +        return x;
    +    }
    +
    +    private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) {
    +        // Build up the result mh as a sequence of fills like this:
    +        //   finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23))
    +        // The various fill(_,10*I,___*[J]) are reusable.
    +        int leftLen = Math.min(nargs, LEFT_ARGS);  // absorb some arguments immediately
    +        int rightLen = nargs - leftLen;
    +        MethodHandle leftCollector = newArray.bindTo(nargs);
    +        leftCollector = leftCollector.asCollector(Object[].class, leftLen);
    +        MethodHandle mh = finisher;
    +        if (rightLen > 0) {
    +            MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen);
    +            if (mh == Lazy.MH_arrayIdentity)
    +                mh = rightFiller;
    +            else
    +                mh = MethodHandles.collectArguments(mh, 0, rightFiller);
    +        }
    +        if (mh == Lazy.MH_arrayIdentity)
    +            mh = leftCollector;
    +        else
    +            mh = MethodHandles.collectArguments(mh, 0, leftCollector);
    +        return mh;
    +    }
    +
    +    private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1);
    +    private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1];
    +    /** fill_array_to_right(N).invoke(a, argL..arg[N-1])
    +     *  fills a[L]..a[N-1] with corresponding arguments,
    +     *  and then returns a.  The value L is a global constant (LEFT_ARGS).
    +     */
    +    private static MethodHandle fillToRight(int nargs) {
    +        MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs];
    +        if (filler != null)  return filler;
    +        filler = buildFiller(nargs);
    +        assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1));
    +        return FILL_ARRAY_TO_RIGHT[nargs] = filler;
    +    }
    +    private static MethodHandle buildFiller(int nargs) {
    +        if (nargs <= LEFT_ARGS)
    +            return Lazy.MH_arrayIdentity;  // no args to fill; return the array unchanged
    +        // we need room for both mh and a in mh.invoke(a, arg*[nargs])
    +        final int CHUNK = LEFT_ARGS;
    +        int rightLen = nargs % CHUNK;
    +        int midLen = nargs - rightLen;
    +        if (rightLen == 0) {
    +            midLen = nargs - (rightLen = CHUNK);
    +            if (FILL_ARRAY_TO_RIGHT[midLen] == null) {
    +                // build some precursors from left to right
    +                for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK)
    +                    if (j > LEFT_ARGS)  fillToRight(j);
    +            }
    +        }
    +        if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS);
    +        assert(rightLen > 0);
    +        MethodHandle midFill = fillToRight(midLen);  // recursive fill
    +        MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen);  // [midLen..nargs-1]
    +        assert(midFill.type().parameterCount()   == 1 + midLen - LEFT_ARGS);
    +        assert(rightFill.type().parameterCount() == 1 + rightLen);
    +
    +        // Combine the two fills:
    +        //   right(mid(a, x10..x19), x20..x23)
    +        // The final product will look like this:
    +        //   right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23)
    +        if (midLen == LEFT_ARGS)
    +            return rightFill;
    +        else
    +            return MethodHandles.collectArguments(rightFill, 0, midFill);
    +    }
    +
    +    // Type-polymorphic version of varargs maker.
    +    private static final ClassValue TYPED_COLLECTORS
    +        = new ClassValue() {
    +            @Override
    +            protected MethodHandle[] computeValue(Class type) {
    +                return new MethodHandle[256];
    +            }
    +    };
    +
    +    static final int MAX_JVM_ARITY = 255;  // limit imposed by the JVM
    +
    +    /** Return a method handle that takes the indicated number of
    +     *  typed arguments and returns an array of them.
    +     *  The type argument is the array type.
    +     */
    +    static MethodHandle varargsArray(Class arrayType, int nargs) {
    +        Class elemType = arrayType.getComponentType();
    +        if (elemType == null)  throw new IllegalArgumentException("not an array: "+arrayType);
    +        // FIXME: Need more special casing and caching here.
    +        if (nargs >= MAX_JVM_ARITY/2 - 1) {
    +            int slots = nargs;
    +            final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1;  // 1 for receiver MH
    +            if (slots <= MAX_ARRAY_SLOTS && elemType.isPrimitive())
    +                slots *= Wrapper.forPrimitiveType(elemType).stackSlots();
    +            if (slots > MAX_ARRAY_SLOTS)
    +                throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs);
    +        }
    +        if (elemType == Object.class)
    +            return varargsArray(nargs);
    +        // other cases:  primitive arrays, subtypes of Object[]
    +        MethodHandle cache[] = TYPED_COLLECTORS.get(elemType);
    +        MethodHandle mh = nargs < cache.length ? cache[nargs] : null;
    +        if (mh != null)  return mh;
    +        if (nargs == 0) {
    +            Object example = java.lang.reflect.Array.newInstance(arrayType.getComponentType(), 0);
    +            mh = MethodHandles.constant(arrayType, example);
    +        } else if (elemType.isPrimitive()) {
    +            MethodHandle builder = Lazy.MH_fillNewArray;
    +            MethodHandle producer = buildArrayProducer(arrayType);
    +            mh = buildVarargsArray(builder, producer, nargs);
    +        } else {
    +            Class objArrayType = arrayType.asSubclass(Object[].class);
    +            Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType);
    +            MethodHandle builder = Lazy.MH_fillNewTypedArray.bindTo(example);
    +            MethodHandle producer = Lazy.MH_arrayIdentity; // must be weakly typed
    +            mh = buildVarargsArray(builder, producer, nargs);
    +        }
    +        mh = mh.asType(MethodType.methodType(arrayType, Collections.>nCopies(nargs, elemType)));
    +        mh = makeIntrinsic(mh, Intrinsic.NEW_ARRAY);
    +        assert(assertCorrectArity(mh, nargs));
    +        if (nargs < cache.length)
    +            cache[nargs] = mh;
    +        return mh;
    +    }
    +
    +    private static MethodHandle buildArrayProducer(Class arrayType) {
    +        Class elemType = arrayType.getComponentType();
    +        assert(elemType.isPrimitive());
    +        return Lazy.MH_copyAsPrimitiveArray.bindTo(Wrapper.forPrimitiveType(elemType));
    +    }
     }
    diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
    index 0f5169e95e2..01c3b33001d 100644
    --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
    +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleNatives.java
    @@ -509,7 +509,7 @@ class MethodHandleNatives {
     
         /**
          * Is this method a caller-sensitive method?
    -     * I.e., does it call Reflection.getCallerClass or a similer method
    +     * I.e., does it call Reflection.getCallerClass or a similar method
          * to ask about the identity of its caller?
          */
         static boolean isCallerSensitive(MemberName mem) {
    diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java
    index 8fec887447b..1167eeb4a2b 100644
    --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java
    +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleProxies.java
    @@ -33,6 +33,7 @@ import java.util.ArrayList;
     import sun.reflect.CallerSensitive;
     import sun.reflect.Reflection;
     import sun.reflect.misc.ReflectUtil;
    +import static java.lang.invoke.MethodHandleStatics.*;
     
     /**
      * This class consists exclusively of static methods that help adapt
    @@ -148,7 +149,7 @@ public class MethodHandleProxies {
         public static
          T asInterfaceInstance(final Class intfc, final MethodHandle target) {
             if (!intfc.isInterface() || !Modifier.isPublic(intfc.getModifiers()))
    -            throw new IllegalArgumentException("not a public interface: "+intfc.getName());
    +            throw newIllegalArgumentException("not a public interface", intfc.getName());
             final MethodHandle mh;
             if (System.getSecurityManager() != null) {
                 final Class caller = Reflection.getCallerClass();
    @@ -165,7 +166,7 @@ public class MethodHandleProxies {
             }
             final Method[] methods = getSingleNameMethods(intfc);
             if (methods == null)
    -            throw new IllegalArgumentException("not a single-method interface: "+intfc.getName());
    +            throw newIllegalArgumentException("not a single-method interface", intfc.getName());
             final MethodHandle[] vaTargets = new MethodHandle[methods.length];
             for (int i = 0; i < methods.length; i++) {
                 Method sm = methods[i];
    @@ -189,7 +190,7 @@ public class MethodHandleProxies {
                             return getArg(method.getName());
                         if (isObjectMethod(method))
                             return callObjectMethod(proxy, method, args);
    -                    throw new InternalError("bad proxy method: "+method);
    +                    throw newInternalError("bad proxy method: "+method);
                     }
                 };
     
    @@ -240,7 +241,7 @@ public class MethodHandleProxies {
                     return (WrapperInstance) x;
             } catch (ClassCastException ex) {
             }
    -        throw new IllegalArgumentException("not a wrapper instance");
    +        throw newIllegalArgumentException("not a wrapper instance");
         }
     
         /**
    diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java
    index 50a14b35d52..c3d9ac12c09 100644
    --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java
    +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandleStatics.java
    @@ -45,16 +45,21 @@ import sun.misc.Unsafe;
         static final boolean DUMP_CLASS_FILES;
         static final boolean TRACE_INTERPRETER;
         static final boolean TRACE_METHOD_LINKAGE;
    -    static final Integer COMPILE_THRESHOLD;
    +    static final boolean USE_LAMBDA_FORM_EDITOR;
    +    static final int COMPILE_THRESHOLD;
    +    static final int PROFILE_LEVEL;
    +
         static {
    -        final Object[] values = { false, false, false, false, null };
    +        final Object[] values = { false, false, false, false, false, null, null };
             AccessController.doPrivileged(new PrivilegedAction() {
                     public Void run() {
                         values[0] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DEBUG_NAMES");
                         values[1] = Boolean.getBoolean("java.lang.invoke.MethodHandle.DUMP_CLASS_FILES");
                         values[2] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_INTERPRETER");
                         values[3] = Boolean.getBoolean("java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE");
    -                    values[4] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD");
    +                    values[4] = Boolean.getBoolean("java.lang.invoke.MethodHandle.USE_LF_EDITOR");
    +                    values[5] = Integer.getInteger("java.lang.invoke.MethodHandle.COMPILE_THRESHOLD", 30);
    +                    values[6] = Integer.getInteger("java.lang.invoke.MethodHandle.PROFILE_LEVEL", 0);
                         return null;
                     }
                 });
    @@ -62,7 +67,9 @@ import sun.misc.Unsafe;
             DUMP_CLASS_FILES          = (Boolean) values[1];
             TRACE_INTERPRETER         = (Boolean) values[2];
             TRACE_METHOD_LINKAGE      = (Boolean) values[3];
    -        COMPILE_THRESHOLD         = (Integer) values[4];
    +        USE_LAMBDA_FORM_EDITOR    = (Boolean) values[4];
    +        COMPILE_THRESHOLD         = (Integer) values[5];
    +        PROFILE_LEVEL             = (Integer) values[6];
         }
     
         /** Tell if any of the debugging switches are turned on.
    @@ -127,7 +134,10 @@ import sun.misc.Unsafe;
         /*non-public*/ static RuntimeException newIllegalArgumentException(String message, Object obj, Object obj2) {
             return new IllegalArgumentException(message(message, obj, obj2));
         }
    +    /** Propagate unchecked exceptions and errors, but wrap anything checked and throw that instead. */
         /*non-public*/ static Error uncaughtException(Throwable ex) {
    +        if (ex instanceof Error)  throw (Error) ex;
    +        if (ex instanceof RuntimeException)  throw (RuntimeException) ex;
             throw newInternalError("uncaught exception", ex);
         }
         static Error NYI() {
    diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
    index ee282752032..ea692345d66 100644
    --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
    +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodHandles.java
    @@ -26,8 +26,8 @@
     package java.lang.invoke;
     
     import java.lang.reflect.*;
    +import java.util.BitSet;
     import java.util.List;
    -import java.util.ArrayList;
     import java.util.Arrays;
     
     import sun.invoke.util.ValueConversions;
    @@ -40,6 +40,7 @@ import sun.security.util.SecurityConstants;
     import java.lang.invoke.LambdaForm.BasicType;
     import static java.lang.invoke.LambdaForm.BasicType.*;
     import static java.lang.invoke.MethodHandleStatics.*;
    +import static java.lang.invoke.MethodHandleImpl.Intrinsic;
     import static java.lang.invoke.MethodHandleNatives.Constants.*;
     import java.util.concurrent.ConcurrentHashMap;
     
    @@ -862,6 +863,8 @@ assertEquals("", (String) MH_newString.invokeExact());
                     return invoker(type);
                 if ("invokeExact".equals(name))
                     return exactInvoker(type);
    +            if ("invokeBasic".equals(name))
    +                return basicInvoker(type);
                 assert(!MemberName.isMethodHandleInvokeName(name));
                 return null;
             }
    @@ -1141,7 +1144,7 @@ return mh1;
                 Class refc = receiver.getClass(); // may get NPE
                 MemberName method = resolveOrFail(REF_invokeSpecial, refc, name, type);
                 MethodHandle mh = getDirectMethodNoRestrict(REF_invokeSpecial, refc, method, findBoundCallerClass(method));
    -            return mh.bindReceiver(receiver).setVarargs(method);
    +            return mh.bindArgumentL(0, receiver).setVarargs(method);
             }
     
             /**
    @@ -1576,7 +1579,7 @@ return mh1;
                     return false;
                 return true;
             }
    -        private MethodHandle restrictReceiver(MemberName method, MethodHandle mh, Class caller) throws IllegalAccessException {
    +        private MethodHandle restrictReceiver(MemberName method, DirectMethodHandle mh, Class caller) throws IllegalAccessException {
                 assert(!method.isStatic());
                 // receiver type of mh is too wide; narrow to caller
                 if (!method.getDeclaringClass().isAssignableFrom(caller)) {
    @@ -1585,7 +1588,9 @@ return mh1;
                 MethodType rawType = mh.type();
                 if (rawType.parameterType(0) == caller)  return mh;
                 MethodType narrowType = rawType.changeParameterType(0, caller);
    -            return mh.viewAsType(narrowType);
    +            assert(!mh.isVarargsCollector());  // viewAsType will lose varargs-ness
    +            assert(mh.viewAsTypeChecks(narrowType, true));
    +            return mh.copyWith(narrowType, mh.form);
             }
     
             /** Check access and get the requested method. */
    @@ -1647,15 +1652,17 @@ return mh1;
                     checkMethod(refKind, refc, method);
                 }
     
    -            MethodHandle mh = DirectMethodHandle.make(refKind, refc, method);
    -            mh = maybeBindCaller(method, mh, callerClass);
    -            mh = mh.setVarargs(method);
    +            DirectMethodHandle dmh = DirectMethodHandle.make(refKind, refc, method);
    +            MethodHandle mh = dmh;
                 // Optionally narrow the receiver argument to refc using restrictReceiver.
                 if (doRestrict &&
                        (refKind == REF_invokeSpecial ||
                            (MethodHandleNatives.refKindHasReceiver(refKind) &&
    -                           restrictProtectedReceiver(method))))
    -                mh = restrictReceiver(method, mh, lookupClass());
    +                           restrictProtectedReceiver(method)))) {
    +                mh = restrictReceiver(method, dmh, lookupClass());
    +            }
    +            mh = maybeBindCaller(method, mh, callerClass);
    +            mh = mh.setVarargs(method);
                 return mh;
             }
             private MethodHandle maybeBindCaller(MemberName method, MethodHandle mh,
    @@ -1687,12 +1694,12 @@ return mh1;
                 // Optionally check with the security manager; this isn't needed for unreflect* calls.
                 if (checkSecurity)
                     checkSecurityManager(refc, field);
    -            MethodHandle mh = DirectMethodHandle.make(refc, field);
    +            DirectMethodHandle dmh = DirectMethodHandle.make(refc, field);
                 boolean doRestrict = (MethodHandleNatives.refKindHasReceiver(refKind) &&
                                         restrictProtectedReceiver(field));
                 if (doRestrict)
    -                mh = restrictReceiver(field, mh, lookupClass());
    -            return mh;
    +                return restrictReceiver(field, dmh, lookupClass());
    +            return dmh;
             }
             /** Check access and get the requested constructor. */
             private MethodHandle getDirectConstructor(Class refc, MemberName ctor) throws IllegalAccessException {
    @@ -1879,7 +1886,8 @@ return invoker;
         static public
         MethodHandle spreadInvoker(MethodType type, int leadingArgCount) {
             if (leadingArgCount < 0 || leadingArgCount > type.parameterCount())
    -            throw new IllegalArgumentException("bad argument count "+leadingArgCount);
    +            throw newIllegalArgumentException("bad argument count", leadingArgCount);
    +        type = type.asSpreaderType(Object[].class, type.parameterCount() - leadingArgCount);
             return type.invokers().spreadInvoker(leadingArgCount);
         }
     
    @@ -1959,12 +1967,12 @@ return invoker;
          */
         static public
         MethodHandle invoker(MethodType type) {
    -        return type.invokers().generalInvoker();
    +        return type.invokers().genericInvoker();
         }
     
         static /*non-public*/
         MethodHandle basicInvoker(MethodType type) {
    -        return type.form().basicInvoker();
    +        return type.invokers().basicInvoker();
         }
     
          /// method handle modification (creation from other method handles)
    @@ -2015,10 +2023,13 @@ return invoker;
          */
         public static
         MethodHandle explicitCastArguments(MethodHandle target, MethodType newType) {
    -        if (!target.type().isCastableTo(newType)) {
    -            throw new WrongMethodTypeException("cannot explicitly cast "+target+" to "+newType);
    +        MethodType oldType = target.type();
    +        // use the asTypeCache when possible:
    +        if (oldType == newType)  return target;
    +        if (oldType.explicitCastEquivalentToAsType(newType)) {
    +            return target.asType(newType);
             }
    -        return MethodHandleImpl.makePairwiseConvert(target, newType, 2);
    +        return MethodHandleImpl.makePairwiseConvert(target, newType, false);
         }
     
         /**
    @@ -2082,12 +2093,165 @@ assert((int)twice.invokeExact(21) == 42);
          */
         public static
         MethodHandle permuteArguments(MethodHandle target, MethodType newType, int... reorder) {
    -        reorder = reorder.clone();
    -        checkReorder(reorder, newType, target.type());
    -        return target.permuteArguments(newType, reorder);
    +        reorder = reorder.clone();  // get a private copy
    +        MethodType oldType = target.type();
    +        permuteArgumentChecks(reorder, newType, oldType);
    +        if (USE_LAMBDA_FORM_EDITOR) {
    +            // first detect dropped arguments and handle them separately
    +            int[] originalReorder = reorder;
    +            BoundMethodHandle result = target.rebind();
    +            LambdaForm form = result.form;
    +            int newArity = newType.parameterCount();
    +            // Normalize the reordering into a real permutation,
    +            // by removing duplicates and adding dropped elements.
    +            // This somewhat improves lambda form caching, as well
    +            // as simplifying the transform by breaking it up into steps.
    +            for (int ddIdx; (ddIdx = findFirstDupOrDrop(reorder, newArity)) != 0; ) {
    +                if (ddIdx > 0) {
    +                    // We found a duplicated entry at reorder[ddIdx].
    +                    // Example:  (x,y,z)->asList(x,y,z)
    +                    // permuted by [1*,0,1] => (a0,a1)=>asList(a1,a0,a1)
    +                    // permuted by [0,1,0*] => (a0,a1)=>asList(a0,a1,a0)
    +                    // The starred element corresponds to the argument
    +                    // deleted by the dupArgumentForm transform.
    +                    int srcPos = ddIdx, dstPos = srcPos, dupVal = reorder[srcPos];
    +                    boolean killFirst = false;
    +                    for (int val; (val = reorder[--dstPos]) != dupVal; ) {
    +                        // Set killFirst if the dup is larger than an intervening position.
    +                        // This will remove at least one inversion from the permutation.
    +                        if (dupVal > val) killFirst = true;
    +                    }
    +                    if (!killFirst) {
    +                        srcPos = dstPos;
    +                        dstPos = ddIdx;
    +                    }
    +                    form = form.editor().dupArgumentForm(1 + srcPos, 1 + dstPos);
    +                    assert (reorder[srcPos] == reorder[dstPos]);
    +                    oldType = oldType.dropParameterTypes(dstPos, dstPos + 1);
    +                    // contract the reordering by removing the element at dstPos
    +                    int tailPos = dstPos + 1;
    +                    System.arraycopy(reorder, tailPos, reorder, dstPos, reorder.length - tailPos);
    +                    reorder = Arrays.copyOf(reorder, reorder.length - 1);
    +                } else {
    +                    int dropVal = ~ddIdx, insPos = 0;
    +                    while (insPos < reorder.length && reorder[insPos] < dropVal) {
    +                        // Find first element of reorder larger than dropVal.
    +                        // This is where we will insert the dropVal.
    +                        insPos += 1;
    +                    }
    +                    Class ptype = newType.parameterType(dropVal);
    +                    form = form.editor().addArgumentForm(1 + insPos, BasicType.basicType(ptype));
    +                    oldType = oldType.insertParameterTypes(insPos, ptype);
    +                    // expand the reordering by inserting an element at insPos
    +                    int tailPos = insPos + 1;
    +                    reorder = Arrays.copyOf(reorder, reorder.length + 1);
    +                    System.arraycopy(reorder, insPos, reorder, tailPos, reorder.length - tailPos);
    +                    reorder[insPos] = dropVal;
    +                }
    +                assert (permuteArgumentChecks(reorder, newType, oldType));
    +            }
    +            assert (reorder.length == newArity);  // a perfect permutation
    +            // Note:  This may cache too many distinct LFs. Consider backing off to varargs code.
    +            form = form.editor().permuteArgumentsForm(1, reorder);
    +            if (newType == result.type() && form == result.internalForm())
    +                return result;
    +            return result.copyWith(newType, form);
    +        } else {
    +            // first detect dropped arguments and handle them separately
    +            MethodHandle originalTarget = target;
    +            int newArity = newType.parameterCount();
    +            for (int dropIdx; (dropIdx = findFirstDrop(reorder, newArity)) >= 0; ) {
    +                // dropIdx is missing from reorder; add it in at the end
    +                int oldArity = reorder.length;
    +                target = dropArguments(target, oldArity, newType.parameterType(dropIdx));
    +                reorder = Arrays.copyOf(reorder, oldArity+1);
    +                reorder[oldArity] = dropIdx;
    +            }
    +            assert(target == originalTarget || permuteArgumentChecks(reorder, newType, target.type()));
    +            // Note:  This may cache too many distinct LFs. Consider backing off to varargs code.
    +            BoundMethodHandle result = target.rebind();
    +            LambdaForm form = result.form.permuteArguments(1, reorder, basicTypes(newType.parameterList()));
    +            return result.copyWith(newType, form);
    +        }
         }
     
    -    private static void checkReorder(int[] reorder, MethodType newType, MethodType oldType) {
    +    /** Return the first value in [0..newArity-1] that is not present in reorder. */
    +    private static int findFirstDrop(int[] reorder, int newArity) {
    +        final int BIT_LIMIT = 63;  // max number of bits in bit mask
    +        if (newArity < BIT_LIMIT) {
    +            long mask = 0;
    +            for (int arg : reorder) {
    +                assert(arg < newArity);
    +                mask |= (1 << arg);
    +            }
    +            if (mask == (1 << newArity) - 1) {
    +                assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
    +                return -1;
    +            }
    +            // find first zero
    +            long zeroBit = Long.lowestOneBit(~mask);
    +            int zeroPos = Long.numberOfTrailingZeros(zeroBit);
    +            assert(zeroPos < newArity);
    +            return zeroPos;
    +        }
    +        BitSet mask = new BitSet(newArity);
    +        for (int arg : reorder) {
    +            assert(arg < newArity);
    +            mask.set(arg);
    +        }
    +        int zeroPos = mask.nextClearBit(0);
    +        if (zeroPos == newArity)
    +            return -1;
    +        return zeroPos;
    +    }
    +
    +    /**
    +     * Return an indication of any duplicate or omission in reorder.
    +     * If the reorder contains a duplicate entry, return the index of the second occurrence.
    +     * Otherwise, return ~(n), for the first n in [0..newArity-1] that is not present in reorder.
    +     * Otherwise, return zero.
    +     * If an element not in [0..newArity-1] is encountered, return reorder.length.
    +     */
    +    private static int findFirstDupOrDrop(int[] reorder, int newArity) {
    +        final int BIT_LIMIT = 63;  // max number of bits in bit mask
    +        if (newArity < BIT_LIMIT) {
    +            long mask = 0;
    +            for (int i = 0; i < reorder.length; i++) {
    +                int arg = reorder[i];
    +                if (arg >= newArity)  return reorder.length;
    +                int bit = 1 << arg;
    +                if ((mask & bit) != 0)
    +                    return i;  // >0 indicates a dup
    +                mask |= bit;
    +            }
    +            if (mask == (1 << newArity) - 1) {
    +                assert(Long.numberOfTrailingZeros(Long.lowestOneBit(~mask)) == newArity);
    +                return 0;
    +            }
    +            // find first zero
    +            long zeroBit = Long.lowestOneBit(~mask);
    +            int zeroPos = Long.numberOfTrailingZeros(zeroBit);
    +            assert(zeroPos < newArity);
    +            return ~zeroPos;
    +        } else {
    +            // same algorithm, different bit set
    +            BitSet mask = new BitSet(newArity);
    +            for (int i = 0; i < reorder.length; i++) {
    +                int arg = reorder[i];
    +                if (arg >= newArity)  return reorder.length;
    +                if (mask.get(arg))
    +                    return i;  // >0 indicates a dup
    +                mask.set(arg);
    +            }
    +            int zeroPos = mask.nextClearBit(0);
    +            if (zeroPos == newArity) {
    +                return 0;
    +            }
    +            return ~zeroPos;
    +        }
    +    }
    +
    +    private static boolean permuteArgumentChecks(int[] reorder, MethodType newType, MethodType oldType) {
             if (newType.returnType() != oldType.returnType())
                 throw newIllegalArgumentException("return types do not match",
                         oldType, newType);
    @@ -2105,7 +2269,7 @@ assert((int)twice.invokeExact(21) == 42);
                         throw newIllegalArgumentException("parameter types do not match after reorder",
                                 oldType, newType);
                 }
    -            if (!bad)  return;
    +            if (!bad)  return true;
             }
             throw newIllegalArgumentException("bad reorder array: "+Arrays.toString(reorder));
         }
    @@ -2131,9 +2295,14 @@ assert((int)twice.invokeExact(21) == 42);
                 if (type == void.class)
                     throw newIllegalArgumentException("void type");
                 Wrapper w = Wrapper.forPrimitiveType(type);
    -            return insertArguments(identity(type), 0, w.convert(value, type));
    +            value = w.convert(value, type);
    +            if (w.zero().equals(value))
    +                return zero(w, type);
    +            return insertArguments(identity(type), 0, value);
             } else {
    -            return identity(type).bindTo(type.cast(value));
    +            if (value == null)
    +                return zero(Wrapper.OBJECT, type);
    +            return identity(type).bindTo(value);
             }
         }
     
    @@ -2146,14 +2315,48 @@ assert((int)twice.invokeExact(21) == 42);
          */
         public static
         MethodHandle identity(Class type) {
    -        if (type == void.class)
    -            throw newIllegalArgumentException("void type");
    -        else if (type == Object.class)
    -            return ValueConversions.identity();
    -        else if (type.isPrimitive())
    -            return ValueConversions.identity(Wrapper.forPrimitiveType(type));
    -        else
    -            return MethodHandleImpl.makeReferenceIdentity(type);
    +        Wrapper btw = (type.isPrimitive() ? Wrapper.forPrimitiveType(type) : Wrapper.OBJECT);
    +        int pos = btw.ordinal();
    +        MethodHandle ident = IDENTITY_MHS[pos];
    +        if (ident == null) {
    +            ident = setCachedMethodHandle(IDENTITY_MHS, pos, makeIdentity(btw.primitiveType()));
    +        }
    +        if (ident.type().returnType() == type)
    +            return ident;
    +        // something like identity(Foo.class); do not bother to intern these
    +        assert(btw == Wrapper.OBJECT);
    +        return makeIdentity(type);
    +    }
    +    private static final MethodHandle[] IDENTITY_MHS = new MethodHandle[Wrapper.values().length];
    +    private static MethodHandle makeIdentity(Class ptype) {
    +        MethodType mtype = MethodType.methodType(ptype, ptype);
    +        LambdaForm lform = LambdaForm.identityForm(BasicType.basicType(ptype));
    +        return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.IDENTITY);
    +    }
    +
    +    private static MethodHandle zero(Wrapper btw, Class rtype) {
    +        int pos = btw.ordinal();
    +        MethodHandle zero = ZERO_MHS[pos];
    +        if (zero == null) {
    +            zero = setCachedMethodHandle(ZERO_MHS, pos, makeZero(btw.primitiveType()));
    +        }
    +        if (zero.type().returnType() == rtype)
    +            return zero;
    +        assert(btw == Wrapper.OBJECT);
    +        return makeZero(rtype);
    +    }
    +    private static final MethodHandle[] ZERO_MHS = new MethodHandle[Wrapper.values().length];
    +    private static MethodHandle makeZero(Class rtype) {
    +        MethodType mtype = MethodType.methodType(rtype);
    +        LambdaForm lform = LambdaForm.zeroForm(BasicType.basicType(rtype));
    +        return MethodHandleImpl.makeIntrinsic(mtype, lform, Intrinsic.ZERO);
    +    }
    +
    +    synchronized private static MethodHandle setCachedMethodHandle(MethodHandle[] cache, int pos, MethodHandle value) {
    +        // Simulate a CAS, to avoid racy duplication of results.
    +        MethodHandle prev = cache[pos];
    +        if (prev != null) return prev;
    +        return cache[pos] = value;
         }
     
         /**
    @@ -2189,6 +2392,37 @@ assert((int)twice.invokeExact(21) == 42);
         public static
         MethodHandle insertArguments(MethodHandle target, int pos, Object... values) {
             int insCount = values.length;
    +        Class[] ptypes = insertArgumentsChecks(target, insCount, pos);
    +        if (insCount == 0)  return target;
    +        BoundMethodHandle result = target.rebind();
    +        for (int i = 0; i < insCount; i++) {
    +            Object value = values[i];
    +            Class ptype = ptypes[pos+i];
    +            if (ptype.isPrimitive()) {
    +                result = insertArgumentPrimitive(result, pos, ptype, value);
    +            } else {
    +                value = ptype.cast(value);  // throw CCE if needed
    +                result = result.bindArgumentL(pos, value);
    +            }
    +        }
    +        return result;
    +    }
    +
    +    private static BoundMethodHandle insertArgumentPrimitive(BoundMethodHandle result, int pos,
    +                                                             Class ptype, Object value) {
    +        Wrapper w = Wrapper.forPrimitiveType(ptype);
    +        // perform unboxing and/or primitive conversion
    +        value = w.convert(value, ptype);
    +        switch (w) {
    +        case INT:     return result.bindArgumentI(pos, (int)value);
    +        case LONG:    return result.bindArgumentJ(pos, (long)value);
    +        case FLOAT:   return result.bindArgumentF(pos, (float)value);
    +        case DOUBLE:  return result.bindArgumentD(pos, (double)value);
    +        default:      return result.bindArgumentI(pos, ValueConversions.widenSubword(value));
    +        }
    +    }
    +
    +    private static Class[] insertArgumentsChecks(MethodHandle target, int insCount, int pos) throws RuntimeException {
             MethodType oldType = target.type();
             int outargs = oldType.parameterCount();
             int inargs  = outargs - insCount;
    @@ -2196,31 +2430,7 @@ assert((int)twice.invokeExact(21) == 42);
                 throw newIllegalArgumentException("too many values to insert");
             if (pos < 0 || pos > inargs)
                 throw newIllegalArgumentException("no argument type to append");
    -        MethodHandle result = target;
    -        for (int i = 0; i < insCount; i++) {
    -            Object value = values[i];
    -            Class ptype = oldType.parameterType(pos+i);
    -            if (ptype.isPrimitive()) {
    -                BasicType btype = I_TYPE;
    -                Wrapper w = Wrapper.forPrimitiveType(ptype);
    -                switch (w) {
    -                case LONG:    btype = J_TYPE; break;
    -                case FLOAT:   btype = F_TYPE; break;
    -                case DOUBLE:  btype = D_TYPE; break;
    -                }
    -                // perform unboxing and/or primitive conversion
    -                value = w.convert(value, ptype);
    -                result = result.bindArgument(pos, btype, value);
    -                continue;
    -            }
    -            value = ptype.cast(value);  // throw CCE if needed
    -            if (pos == 0) {
    -                result = result.bindReceiver(value);
    -            } else {
    -                result = result.bindArgument(pos, L_TYPE, value);
    -            }
    -        }
    -        return result;
    +        return oldType.ptypes();
         }
     
         /**
    @@ -2268,18 +2478,33 @@ assertEquals("yz", (String) d0.invokeExact(123, "x", "y", "z"));
         public static
         MethodHandle dropArguments(MethodHandle target, int pos, List> valueTypes) {
             MethodType oldType = target.type();  // get NPE
    +        int dropped = dropArgumentChecks(oldType, pos, valueTypes);
    +        if (dropped == 0)  return target;
    +        BoundMethodHandle result = target.rebind();
    +        LambdaForm lform = result.form;
    +        if (USE_LAMBDA_FORM_EDITOR) {
    +            int insertFormArg = 1 + pos;
    +            for (Class ptype : valueTypes) {
    +                lform = lform.editor().addArgumentForm(insertFormArg++, BasicType.basicType(ptype));
    +            }
    +        } else {
    +            lform = lform.addArguments(pos, valueTypes);
    +        }
    +        MethodType newType = oldType.insertParameterTypes(pos, valueTypes);
    +        result = result.copyWith(newType, lform);
    +        return result;
    +    }
    +
    +    private static int dropArgumentChecks(MethodType oldType, int pos, List> valueTypes) {
             int dropped = valueTypes.size();
             MethodType.checkSlotCount(dropped);
    -        if (dropped == 0)  return target;
             int outargs = oldType.parameterCount();
             int inargs  = outargs + dropped;
    -        if (pos < 0 || pos >= inargs)
    -            throw newIllegalArgumentException("no argument type to remove");
    -        ArrayList> ptypes = new ArrayList<>(oldType.parameterList());
    -        ptypes.addAll(pos, valueTypes);
    -        if (ptypes.size() != inargs)  throw newIllegalArgumentException("valueTypes");
    -        MethodType newType = MethodType.methodType(oldType.returnType(), ptypes);
    -        return target.dropArguments(newType, pos, dropped);
    +        if (pos < 0 || pos > outargs)
    +            throw newIllegalArgumentException("no argument type to remove"
    +                    + Arrays.asList(oldType, pos, valueTypes, inargs, outargs)
    +                    );
    +        return dropped;
         }
     
         /**
    @@ -2401,32 +2626,47 @@ assertEquals("XY", (String) f2.invokeExact("x", "y")); // XY
          */
         public static
         MethodHandle filterArguments(MethodHandle target, int pos, MethodHandle... filters) {
    -        MethodType targetType = target.type();
    +        filterArgumentsCheckArity(target, pos, filters);
             MethodHandle adapter = target;
    -        MethodType adapterType = null;
    -        assert((adapterType = targetType) != null);
    -        int maxPos = targetType.parameterCount();
    -        if (pos + filters.length > maxPos)
    -            throw newIllegalArgumentException("too many filters");
             int curPos = pos-1;  // pre-incremented
             for (MethodHandle filter : filters) {
                 curPos += 1;
                 if (filter == null)  continue;  // ignore null elements of filters
                 adapter = filterArgument(adapter, curPos, filter);
    -            assert((adapterType = adapterType.changeParameterType(curPos, filter.type().parameterType(0))) != null);
             }
    -        assert(adapterType.equals(adapter.type()));
             return adapter;
         }
     
         /*non-public*/ static
         MethodHandle filterArgument(MethodHandle target, int pos, MethodHandle filter) {
    +        filterArgumentChecks(target, pos, filter);
    +        if (USE_LAMBDA_FORM_EDITOR) {
    +            MethodType targetType = target.type();
    +            MethodType filterType = filter.type();
    +            BoundMethodHandle result = target.rebind();
    +            Class newParamType = filterType.parameterType(0);
    +            LambdaForm lform = result.editor().filterArgumentForm(1 + pos, BasicType.basicType(newParamType));
    +            MethodType newType = targetType.changeParameterType(pos, newParamType);
    +            result = result.copyWithExtendL(newType, lform, filter);
    +            return result;
    +        } else {
    +            return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
    +        }
    +    }
    +
    +    private static void filterArgumentsCheckArity(MethodHandle target, int pos, MethodHandle[] filters) {
    +        MethodType targetType = target.type();
    +        int maxPos = targetType.parameterCount();
    +        if (pos + filters.length > maxPos)
    +            throw newIllegalArgumentException("too many filters");
    +    }
    +
    +    private static void filterArgumentChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException {
             MethodType targetType = target.type();
             MethodType filterType = filter.type();
             if (filterType.parameterCount() != 1
                 || filterType.returnType() != targetType.parameterType(pos))
                 throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
    -        return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
         }
     
         /**
    @@ -2537,12 +2777,36 @@ assertEquals("[top, [[up, down, strange], charm], bottom]",
          */
         public static
         MethodHandle collectArguments(MethodHandle target, int pos, MethodHandle filter) {
    +        MethodType newType = collectArgumentsChecks(target, pos, filter);
    +        if (USE_LAMBDA_FORM_EDITOR) {
    +            MethodType collectorType = filter.type();
    +            BoundMethodHandle result = target.rebind();
    +            LambdaForm lform;
    +            if (collectorType.returnType().isArray() && filter.intrinsicName() == Intrinsic.NEW_ARRAY) {
    +                lform = result.editor().collectArgumentArrayForm(1 + pos, filter);
    +                if (lform != null) {
    +                    return result.copyWith(newType, lform);
    +                }
    +            }
    +            lform = result.editor().collectArgumentsForm(1 + pos, collectorType.basicType());
    +            return result.copyWithExtendL(newType, lform, filter);
    +        } else {
    +            return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
    +        }
    +    }
    +
    +    private static MethodType collectArgumentsChecks(MethodHandle target, int pos, MethodHandle filter) throws RuntimeException {
             MethodType targetType = target.type();
             MethodType filterType = filter.type();
    -        if (filterType.returnType() != void.class &&
    -            filterType.returnType() != targetType.parameterType(pos))
    +        Class rtype = filterType.returnType();
    +        List> filterArgs = filterType.parameterList();
    +        if (rtype == void.class) {
    +            return targetType.insertParameterTypes(pos, filterArgs);
    +        }
    +        if (rtype != targetType.parameterType(pos)) {
                 throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
    -        return MethodHandleImpl.makeCollectArguments(target, filter, pos, false);
    +        }
    +        return targetType.dropParameterTypes(pos, pos+1).insertParameterTypes(pos, filterArgs);
         }
     
         /**
    @@ -2606,15 +2870,26 @@ System.out.println((int) f0.invokeExact("x", "y")); // 2
         MethodHandle filterReturnValue(MethodHandle target, MethodHandle filter) {
             MethodType targetType = target.type();
             MethodType filterType = filter.type();
    +        filterReturnValueChecks(targetType, filterType);
    +        if (USE_LAMBDA_FORM_EDITOR) {
    +            BoundMethodHandle result = target.rebind();
    +            BasicType rtype = BasicType.basicType(filterType.returnType());
    +            LambdaForm lform = result.editor().filterReturnForm(rtype, false);
    +            MethodType newType = targetType.changeReturnType(filterType.returnType());
    +            result = result.copyWithExtendL(newType, lform, filter);
    +            return result;
    +        } else {
    +            return MethodHandleImpl.makeCollectArguments(filter, target, 0, false);
    +        }
    +    }
    +
    +    private static void filterReturnValueChecks(MethodType targetType, MethodType filterType) throws RuntimeException {
             Class rtype = targetType.returnType();
             int filterValues = filterType.parameterCount();
             if (filterValues == 0
                     ? (rtype != void.class)
                     : (rtype != filterType.parameterType(0)))
    -            throw newIllegalArgumentException("target and filter types do not match", target, filter);
    -        // result = fold( lambda(retval, arg...) { filter(retval) },
    -        //                lambda(        arg...) { target(arg...) } )
    -        return MethodHandleImpl.makeCollectArguments(filter, target, 0, false);
    +            throw newIllegalArgumentException("target and filter types do not match", targetType, filterType);
         }
     
         /**
    @@ -2695,24 +2970,40 @@ assertEquals("boojum", (String) catTrace.invokeExact("boo", "jum"));
          */
         public static
         MethodHandle foldArguments(MethodHandle target, MethodHandle combiner) {
    -        int pos = 0;
    +        int foldPos = 0;
             MethodType targetType = target.type();
             MethodType combinerType = combiner.type();
    -        int foldPos = pos;
    -        int foldArgs = combinerType.parameterCount();
    -        int foldVals = combinerType.returnType() == void.class ? 0 : 1;
    +        Class rtype = foldArgumentChecks(foldPos, targetType, combinerType);
    +        if (USE_LAMBDA_FORM_EDITOR) {
    +            BoundMethodHandle result = target.rebind();
    +            boolean dropResult = (rtype == void.class);
    +            // Note:  This may cache too many distinct LFs. Consider backing off to varargs code.
    +            LambdaForm lform = result.editor().foldArgumentsForm(1 + foldPos, dropResult, combinerType.basicType());
    +            MethodType newType = targetType;
    +            if (!dropResult)
    +                newType = newType.dropParameterTypes(foldPos, foldPos + 1);
    +            result = result.copyWithExtendL(newType, lform, combiner);
    +            return result;
    +        } else {
    +            return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true);
    +        }
    +    }
    +
    +    private static Class foldArgumentChecks(int foldPos, MethodType targetType, MethodType combinerType) {
    +        int foldArgs   = combinerType.parameterCount();
    +        Class rtype = combinerType.returnType();
    +        int foldVals = rtype == void.class ? 0 : 1;
             int afterInsertPos = foldPos + foldVals;
             boolean ok = (targetType.parameterCount() >= afterInsertPos + foldArgs);
             if (ok && !(combinerType.parameterList()
                         .equals(targetType.parameterList().subList(afterInsertPos,
                                                                    afterInsertPos + foldArgs))))
                 ok = false;
    -        if (ok && foldVals != 0 && !combinerType.returnType().equals(targetType.parameterType(0)))
    +        if (ok && foldVals != 0 && combinerType.returnType() != targetType.parameterType(0))
                 ok = false;
             if (!ok)
                 throw misMatchedTypes("target and combiner types", targetType, combinerType);
    -        MethodType newType = targetType.dropParameterTypes(foldPos, afterInsertPos);
    -        return MethodHandleImpl.makeCollectArguments(target, combiner, foldPos, true);
    +        return rtype;
         }
     
         /**
    diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java
    index c26460048b0..2762227f5c2 100644
    --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java
    +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodType.java
    @@ -33,6 +33,7 @@ import java.util.Arrays;
     import java.util.Collections;
     import java.util.List;
     import java.util.Objects;
    +import java.util.StringJoiner;
     import java.util.concurrent.ConcurrentMap;
     import java.util.concurrent.ConcurrentHashMap;
     import sun.invoke.util.BytecodeDescriptor;
    @@ -466,6 +467,75 @@ class MethodType implements java.io.Serializable {
             return dropParameterTypes(start, end).insertParameterTypes(start, ptypesToInsert);
         }
     
    +    /** Replace the last arrayLength parameter types with the component type of arrayType.
    +     * @param arrayType any array type
    +     * @param arrayLength the number of parameter types to change
    +     * @return the resulting type
    +     */
    +    /*non-public*/ MethodType asSpreaderType(Class arrayType, int arrayLength) {
    +        assert(parameterCount() >= arrayLength);
    +        int spreadPos = ptypes.length - arrayLength;
    +        if (arrayLength == 0)  return this;  // nothing to change
    +        if (arrayType == Object[].class) {
    +            if (isGeneric())  return this;  // nothing to change
    +            if (spreadPos == 0) {
    +                // no leading arguments to preserve; go generic
    +                MethodType res = genericMethodType(arrayLength);
    +                if (rtype != Object.class) {
    +                    res = res.changeReturnType(rtype);
    +                }
    +                return res;
    +            }
    +        }
    +        Class elemType = arrayType.getComponentType();
    +        assert(elemType != null);
    +        for (int i = spreadPos; i < ptypes.length; i++) {
    +            if (ptypes[i] != elemType) {
    +                Class[] fixedPtypes = ptypes.clone();
    +                Arrays.fill(fixedPtypes, i, ptypes.length, elemType);
    +                return methodType(rtype, fixedPtypes);
    +            }
    +        }
    +        return this;  // arguments check out; no change
    +    }
    +
    +    /** Return the leading parameter type, which must exist and be a reference.
    +     *  @return the leading parameter type, after error checks
    +     */
    +    /*non-public*/ Class leadingReferenceParameter() {
    +        Class ptype;
    +        if (ptypes.length == 0 ||
    +            (ptype = ptypes[0]).isPrimitive())
    +            throw newIllegalArgumentException("no leading reference parameter");
    +        return ptype;
    +    }
    +
    +    /** Delete the last parameter type and replace it with arrayLength copies of the component type of arrayType.
    +     * @param arrayType any array type
    +     * @param arrayLength the number of parameter types to insert
    +     * @return the resulting type
    +     */
    +    /*non-public*/ MethodType asCollectorType(Class arrayType, int arrayLength) {
    +        assert(parameterCount() >= 1);
    +        assert(lastParameterType().isAssignableFrom(arrayType));
    +        MethodType res;
    +        if (arrayType == Object[].class) {
    +            res = genericMethodType(arrayLength);
    +            if (rtype != Object.class) {
    +                res = res.changeReturnType(rtype);
    +            }
    +        } else {
    +            Class elemType = arrayType.getComponentType();
    +            assert(elemType != null);
    +            res = methodType(rtype, Collections.nCopies(arrayLength, elemType));
    +        }
    +        if (ptypes.length == 1) {
    +            return res;
    +        } else {
    +            return res.insertParameterTypes(0, parameterList().subList(0, ptypes.length-1));
    +        }
    +    }
    +
         /**
          * Finds or creates a method type with some parameter types omitted.
          * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
    @@ -573,6 +643,10 @@ class MethodType implements java.io.Serializable {
             return genericMethodType(parameterCount());
         }
     
    +    /*non-public*/ boolean isGeneric() {
    +        return this == erase() && !hasPrimitives();
    +    }
    +
         /**
          * Converts all primitive types to their corresponding wrapper types.
          * Convenience method for {@link #methodType(java.lang.Class, java.lang.Class[]) methodType}.
    @@ -717,55 +791,145 @@ class MethodType implements java.io.Serializable {
          */
         @Override
         public String toString() {
    -        StringBuilder sb = new StringBuilder();
    -        sb.append("(");
    +        StringJoiner sj = new StringJoiner(",", "(",
    +                ")" + rtype.getSimpleName());
             for (int i = 0; i < ptypes.length; i++) {
    -            if (i > 0)  sb.append(",");
    -            sb.append(ptypes[i].getSimpleName());
    +            sj.add(ptypes[i].getSimpleName());
             }
    -        sb.append(")");
    -        sb.append(rtype.getSimpleName());
    -        return sb.toString();
    +        return sj.toString();
         }
     
    -
    +    /** True if the old return type can always be viewed (w/o casting) under new return type,
    +     *  and the new parameters can be viewed (w/o casting) under the old parameter types.
    +     */
         /*non-public*/
    -    boolean isViewableAs(MethodType newType) {
    -        if (!VerifyType.isNullConversion(returnType(), newType.returnType()))
    +    boolean isViewableAs(MethodType newType, boolean keepInterfaces) {
    +        if (!VerifyType.isNullConversion(returnType(), newType.returnType(), keepInterfaces))
                 return false;
    +        return parametersAreViewableAs(newType, keepInterfaces);
    +    }
    +    /** True if the new parameters can be viewed (w/o casting) under the old parameter types. */
    +    /*non-public*/
    +    boolean parametersAreViewableAs(MethodType newType, boolean keepInterfaces) {
    +        if (form == newType.form && form.erasedType == this)
    +            return true;  // my reference parameters are all Object
    +        if (ptypes == newType.ptypes)
    +            return true;
             int argc = parameterCount();
             if (argc != newType.parameterCount())
                 return false;
             for (int i = 0; i < argc; i++) {
    -            if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i)))
    +            if (!VerifyType.isNullConversion(newType.parameterType(i), parameterType(i), keepInterfaces))
                     return false;
             }
             return true;
         }
         /*non-public*/
    -    boolean isCastableTo(MethodType newType) {
    -        int argc = parameterCount();
    -        if (argc != newType.parameterCount())
    -            return false;
    -        return true;
    -    }
    -    /*non-public*/
         boolean isConvertibleTo(MethodType newType) {
    +        MethodTypeForm oldForm = this.form();
    +        MethodTypeForm newForm = newType.form();
    +        if (oldForm == newForm)
    +            // same parameter count, same primitive/object mix
    +            return true;
             if (!canConvert(returnType(), newType.returnType()))
                 return false;
    -        int argc = parameterCount();
    -        if (argc != newType.parameterCount())
    +        Class[] srcTypes = newType.ptypes;
    +        Class[] dstTypes = ptypes;
    +        if (srcTypes == dstTypes)
    +            return true;
    +        int argc;
    +        if ((argc = srcTypes.length) != dstTypes.length)
                 return false;
    -        for (int i = 0; i < argc; i++) {
    -            if (!canConvert(newType.parameterType(i), parameterType(i)))
    +        if (argc <= 1) {
    +            if (argc == 1 && !canConvert(srcTypes[0], dstTypes[0]))
                     return false;
    +            return true;
    +        }
    +        if ((oldForm.primitiveParameterCount() == 0 && oldForm.erasedType == this) ||
    +            (newForm.primitiveParameterCount() == 0 && newForm.erasedType == newType)) {
    +            // Somewhat complicated test to avoid a loop of 2 or more trips.
    +            // If either type has only Object parameters, we know we can convert.
    +            assert(canConvertParameters(srcTypes, dstTypes));
    +            return true;
    +        }
    +        return canConvertParameters(srcTypes, dstTypes);
    +    }
    +
    +    /** Returns true if MHs.explicitCastArguments produces the same result as MH.asType.
    +     *  If the type conversion is impossible for either, the result should be false.
    +     */
    +    /*non-public*/
    +    boolean explicitCastEquivalentToAsType(MethodType newType) {
    +        if (this == newType)  return true;
    +        if (!explicitCastEquivalentToAsType(rtype, newType.rtype)) {
    +            return false;
    +        }
    +        Class[] srcTypes = newType.ptypes;
    +        Class[] dstTypes = ptypes;
    +        if (dstTypes == srcTypes) {
    +            return true;
    +        }
    +        if (dstTypes.length != srcTypes.length) {
    +            return false;
    +        }
    +        for (int i = 0; i < dstTypes.length; i++) {
    +            if (!explicitCastEquivalentToAsType(srcTypes[i], dstTypes[i])) {
    +                return false;
    +            }
             }
             return true;
         }
    +
    +    /** Reports true if the src can be converted to the dst, by both asType and MHs.eCE,
    +     *  and with the same effect.
    +     *  MHs.eCA has the following "upgrades" to MH.asType:
    +     *  1. interfaces are unchecked (that is, treated as if aliased to Object)
    +     *     Therefore, {@code Object->CharSequence} is possible in both cases but has different semantics
    +     *  2. the full matrix of primitive-to-primitive conversions is supported
    +     *     Narrowing like {@code long->byte} and basic-typing like {@code boolean->int}
    +     *     are not supported by asType, but anything supported by asType is equivalent
    +     *     with MHs.eCE.
    +     *  3a. unboxing conversions can be followed by the full matrix of primitive conversions
    +     *  3b. unboxing of null is permitted (creates a zero primitive value)
    +     *     Most unboxing conversions, like {@code Object->int}, has potentially
    +     *     different behaviors for asType vs. MHs.eCE, because the dynamic value
    +     *     might be a wrapper of a type that requires narrowing, like {@code (Object)1L->byte}.
    +     *     The equivalence is only certain if the static src type is a wrapper,
    +     *     and the conversion will be a widening one.
    +     * Other than interfaces, reference-to-reference conversions are the same.
    +     * Boxing primitives to references is the same for both operators.
    +     */
    +    private static boolean explicitCastEquivalentToAsType(Class src, Class dst) {
    +        if (src == dst || dst == Object.class || dst == void.class)  return true;
    +        if (src.isPrimitive()) {
    +            // Could be a prim/prim conversion, where casting is a strict superset.
    +            // Or a boxing conversion, which is always to an exact wrapper class.
    +            return canConvert(src, dst);
    +        } else if (dst.isPrimitive()) {
    +            Wrapper dw = Wrapper.forPrimitiveType(dst);
    +            // Watch out:  If src is Number or Object, we could get dynamic narrowing conversion.
    +            // The conversion is known to be widening only if the wrapper type is statically visible.
    +            return (Wrapper.isWrapperType(src) &&
    +                    dw.isConvertibleFrom(Wrapper.forWrapperType(src)));
    +        } else {
    +            // R->R always works, but we have to avoid a check-cast to an interface.
    +            return !dst.isInterface() || dst.isAssignableFrom(src);
    +        }
    +    }
    +
    +    private boolean canConvertParameters(Class[] srcTypes, Class[] dstTypes) {
    +        for (int i = 0; i < srcTypes.length; i++) {
    +            if (!canConvert(srcTypes[i], dstTypes[i])) {
    +                return false;
    +            }
    +        }
    +        return true;
    +    }
    +
         /*non-public*/
         static boolean canConvert(Class src, Class dst) {
             // short-circuit a few cases:
    -        if (src == dst || dst == Object.class)  return true;
    +        if (src == dst || src == Object.class || dst == Object.class)  return true;
             // the remainder of this logic is documented in MethodHandle.asType
             if (src.isPrimitive()) {
                 // can force void to an explicit null, a la reflect.Method.invoke
    @@ -907,7 +1071,7 @@ class MethodType implements java.io.Serializable {
             if (!descriptor.startsWith("(") ||  // also generates NPE if needed
                 descriptor.indexOf(')') < 0 ||
                 descriptor.indexOf('.') >= 0)
    -            throw new IllegalArgumentException("not a method descriptor: "+descriptor);
    +            throw newIllegalArgumentException("not a method descriptor: "+descriptor);
             List> types = BytecodeDescriptor.parseMethod(descriptor, loader);
             Class rtype = types.remove(types.size() - 1);
             checkSlotCount(types.size());
    diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java b/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
    index d34a2998cab..43e85589410 100644
    --- a/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
    +++ b/jdk/src/java.base/share/classes/java/lang/invoke/MethodTypeForm.java
    @@ -47,15 +47,17 @@ final class MethodTypeForm {
         final int[] argToSlotTable, slotToArgTable;
         final long argCounts;               // packed slot & value counts
         final long primCounts;              // packed prim & double counts
    -    final int vmslots;                  // total number of parameter slots
         final MethodType erasedType;        // the canonical erasure
         final MethodType basicType;         // the canonical erasure, with primitives simplified
     
         // Cached adapter information:
    -    @Stable String typeString;           // argument type signature characters
    -    @Stable MethodHandle genericInvoker; // JVM hook for inexact invoke
    -    @Stable MethodHandle basicInvoker;   // cached instance of MH.invokeBasic
    -    @Stable MethodHandle namedFunctionInvoker; // cached helper for LF.NamedFunction
    +    @Stable final MethodHandle[] methodHandles;
    +    // Indexes into methodHandles:
    +    static final int
    +            MH_BASIC_INV      =  0,  // cached instance of MH.invokeBasic
    +            MH_NF_INV         =  1,  // cached helper for LF.NamedFunction
    +            MH_UNINIT_CS      =  2,  // uninitialized call site
    +            MH_LIMIT          =  3;
     
         // Cached lambda form information, for basic types only:
         final @Stable LambdaForm[] lambdaForms;
    @@ -68,26 +70,55 @@ final class MethodTypeForm {
                 LF_INVINTERFACE   =  4,
                 LF_INVSTATIC_INIT =  5,  // DMH invokeStatic with  barrier
                 LF_INTERPRET      =  6,  // LF interpreter
    -            LF_COUNTER        =  7,  // CMH wrapper
    -            LF_REINVOKE       =  8,  // other wrapper
    -            LF_EX_LINKER      =  9,  // invokeExact_MT
    -            LF_EX_INVOKER     = 10,  // invokeExact MH
    -            LF_GEN_LINKER     = 11,
    -            LF_GEN_INVOKER    = 12,
    +            LF_REBIND         =  7,  // BoundMethodHandle
    +            LF_DELEGATE       =  8,  // DelegatingMethodHandle
    +            LF_EX_LINKER      =  9,  // invokeExact_MT (for invokehandle)
    +            LF_EX_INVOKER     = 10,  // MHs.invokeExact
    +            LF_GEN_LINKER     = 11,  // generic invoke_MT (for invokehandle)
    +            LF_GEN_INVOKER    = 12,  // generic MHs.invoke
                 LF_CS_LINKER      = 13,  // linkToCallSite_CS
                 LF_MH_LINKER      = 14,  // linkToCallSite_MH
    -            LF_GWC            = 15,
    -            LF_LIMIT          = 16;
    +            LF_GWC            = 15,  // guardWithCatch (catchException)
    +            LF_GWT            = 16,  // guardWithTest
    +            LF_LIMIT          = 17;
     
    +    /** Return the type corresponding uniquely (1-1) to this MT-form.
    +     *  It might have any primitive returns or arguments, but will have no references except Object.
    +     */
         public MethodType erasedType() {
             return erasedType;
         }
     
    +    /** Return the basic type derived from the erased type of this MT-form.
    +     *  A basic type is erased (all references Object) and also has all primitive
    +     *  types (except int, long, float, double, void) normalized to int.
    +     *  Such basic types correspond to low-level JVM calling sequences.
    +     */
         public MethodType basicType() {
             return basicType;
         }
     
    +    private boolean assertIsBasicType() {
    +        // primitives must be flattened also
    +        assert(erasedType == basicType)
    +                : "erasedType: " + erasedType + " != basicType: " + basicType;
    +        return true;
    +    }
    +
    +    public MethodHandle cachedMethodHandle(int which) {
    +        assert(assertIsBasicType());
    +        return methodHandles[which];
    +    }
    +
    +    synchronized public MethodHandle setCachedMethodHandle(int which, MethodHandle mh) {
    +        // Simulate a CAS, to avoid racy duplication of results.
    +        MethodHandle prev = methodHandles[which];
    +        if (prev != null)  return prev;
    +        return methodHandles[which] = mh;
    +    }
    +
         public LambdaForm cachedLambdaForm(int which) {
    +        assert(assertIsBasicType());
             return lambdaForms[which];
         }
     
    @@ -98,28 +129,6 @@ final class MethodTypeForm {
             return lambdaForms[which] = form;
         }
     
    -    public MethodHandle basicInvoker() {
    -        assert(erasedType == basicType) : "erasedType: " + erasedType + " != basicType: " + basicType;  // primitives must be flattened also
    -        MethodHandle invoker = basicInvoker;
    -        if (invoker != null)  return invoker;
    -        invoker = DirectMethodHandle.make(invokeBasicMethod(basicType));
    -        basicInvoker = invoker;
    -        return invoker;
    -    }
    -
    -    // This next one is called from LambdaForm.NamedFunction..
    -    /*non-public*/ static MemberName invokeBasicMethod(MethodType basicType) {
    -        assert(basicType == basicType.basicType());
    -        try {
    -            // Do approximately the same as this public API call:
    -            //   Lookup.findVirtual(MethodHandle.class, name, type);
    -            // But bypass access and corner case checks, since we know exactly what we need.
    -            return IMPL_LOOKUP.resolveOrFail(REF_invokeVirtual, MethodHandle.class, "invokeBasic", basicType);
    -         } catch (ReflectiveOperationException ex) {
    -            throw newInternalError("JVM cannot find invoker for "+basicType, ex);
    -        }
    -    }
    -
         /**
          * Build an MTF for a given type, which must have all references erased to Object.
          * This MTF will stand for that type and all un-erased variations.
    @@ -172,6 +181,16 @@ final class MethodTypeForm {
                 this.basicType = erasedType;
             } else {
                 this.basicType = MethodType.makeImpl(bt, bpts, true);
    +            // fill in rest of data from the basic type:
    +            MethodTypeForm that = this.basicType.form();
    +            assert(this != that);
    +            this.primCounts = that.primCounts;
    +            this.argCounts = that.argCounts;
    +            this.argToSlotTable = that.argToSlotTable;
    +            this.slotToArgTable = that.slotToArgTable;
    +            this.methodHandles = null;
    +            this.lambdaForms = null;
    +            return;
             }
             if (lac != 0) {
                 int slot = ptypeCount + lac;
    @@ -187,10 +206,14 @@ final class MethodTypeForm {
                     argToSlotTab[1+i]  = slot;
                 }
                 assert(slot == 0);  // filled the table
    -        }
    -        this.primCounts = pack(lrc, prc, lac, pac);
    -        this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
    -        if (slotToArgTab == null) {
    +        } else if (pac != 0) {
    +            // have primitives but no long primitives; share slot counts with generic
    +            assert(ptypeCount == pslotCount);
    +            MethodTypeForm that = MethodType.genericMethodType(ptypeCount).form();
    +            assert(this != that);
    +            slotToArgTab = that.slotToArgTable;
    +            argToSlotTab = that.argToSlotTable;
    +        } else {
                 int slot = ptypeCount; // first arg is deepest in stack
                 slotToArgTab = new int[slot+1];
                 argToSlotTab = new int[1+ptypeCount];
    @@ -201,19 +224,17 @@ final class MethodTypeForm {
                     argToSlotTab[1+i]  = slot;
                 }
             }
    +        this.primCounts = pack(lrc, prc, lac, pac);
    +        this.argCounts = pack(rslotCount, rtypeCount, pslotCount, ptypeCount);
             this.argToSlotTable = argToSlotTab;
             this.slotToArgTable = slotToArgTab;
     
             if (pslotCount >= 256)  throw newIllegalArgumentException("too many arguments");
     
    -        // send a few bits down to the JVM:
    -        this.vmslots = parameterSlotCount();
    -
    -        if (basicType == erasedType) {
    -            lambdaForms = new LambdaForm[LF_LIMIT];
    -        } else {
    -            lambdaForms = null;  // could be basicType.form().lambdaForms;
    -        }
    +        // Initialize caches, but only for basic types
    +        assert(basicType == erasedType);
    +        this.lambdaForms = new LambdaForm[LF_LIMIT];
    +        this.methodHandles = new MethodHandle[MH_LIMIT];
         }
     
         private static long pack(int a, int b, int c, int d) {
    @@ -300,7 +321,7 @@ final class MethodTypeForm {
          */
         public static MethodType canonicalize(MethodType mt, int howRet, int howArgs) {
             Class[] ptypes = mt.ptypes();
    -        Class[] ptc = MethodTypeForm.canonicalizes(ptypes, howArgs);
    +        Class[] ptc = MethodTypeForm.canonicalizeAll(ptypes, howArgs);
             Class rtype = mt.returnType();
             Class rtc = MethodTypeForm.canonicalize(rtype, howRet);
             if (ptc == null && rtc == null) {
    @@ -368,7 +389,7 @@ final class MethodTypeForm {
         /** Canonicalize each param type in the given array.
          *  Return null if all types are already canonicalized.
          */
    -    static Class[] canonicalizes(Class[] ts, int how) {
    +    static Class[] canonicalizeAll(Class[] ts, int how) {
             Class[] cs = null;
             for (int imax = ts.length, i = 0; i < imax; i++) {
                 Class c = canonicalize(ts[i], how);
    diff --git a/jdk/src/java.base/share/classes/java/lang/invoke/SimpleMethodHandle.java b/jdk/src/java.base/share/classes/java/lang/invoke/SimpleMethodHandle.java
    index 752505ee68e..c9e37a81ff4 100644
    --- a/jdk/src/java.base/share/classes/java/lang/invoke/SimpleMethodHandle.java
    +++ b/jdk/src/java.base/share/classes/java/lang/invoke/SimpleMethodHandle.java
    @@ -25,38 +25,77 @@
     
     package java.lang.invoke;
     
    -import static java.lang.invoke.LambdaForm.*;
     import static java.lang.invoke.LambdaForm.BasicType.*;
    +import static java.lang.invoke.MethodHandleStatics.*;
     
     /**
      * A method handle whose behavior is determined only by its LambdaForm.
      * @author jrose
      */
    -final class SimpleMethodHandle extends MethodHandle {
    +final class SimpleMethodHandle extends BoundMethodHandle {
         private SimpleMethodHandle(MethodType type, LambdaForm form) {
             super(type, form);
         }
     
    -    /*non-public*/ static SimpleMethodHandle make(MethodType type, LambdaForm form) {
    +    /*non-public*/ static BoundMethodHandle make(MethodType type, LambdaForm form) {
             return new SimpleMethodHandle(type, form);
         }
     
    -    @Override
    -    MethodHandle bindArgument(int pos, BasicType basicType, Object value) {
    -        MethodType type2 = type().dropParameterTypes(pos, pos+1);
    -        LambdaForm form2 = internalForm().bind(1+pos, BoundMethodHandle.SpeciesData.EMPTY);
    -        return BoundMethodHandle.bindSingle(type2, form2, basicType, value);
    +    /*non-public*/ static final SpeciesData SPECIES_DATA = SpeciesData.EMPTY;
    +
    +    /*non-public*/ public SpeciesData speciesData() {
    +            return SPECIES_DATA;
         }
     
         @Override
    -    MethodHandle dropArguments(MethodType srcType, int pos, int drops) {
    -        LambdaForm newForm = internalForm().addArguments(pos, srcType.parameterList().subList(pos, pos+drops));
    -        return new SimpleMethodHandle(srcType, newForm);
    +    /*non-public*/ BoundMethodHandle copyWith(MethodType mt, LambdaForm lf) {
    +        return make(mt, lf);
         }
     
         @Override
    -    MethodHandle permuteArguments(MethodType newType, int[] reorder) {
    -        LambdaForm form2 = internalForm().permuteArguments(1, reorder, basicTypes(newType.parameterList()));
    -        return new SimpleMethodHandle(newType, form2);
    +    String internalProperties() {
    +        return "\n& Class="+getClass().getSimpleName();
    +    }
    +
    +    @Override
    +    /*non-public*/ public int fieldCount() {
    +        return 0;
    +    }
    +
    +    @Override
    +    /*non-public*/ final BoundMethodHandle copyWithExtendL(MethodType mt, LambdaForm lf, Object narg) {
    +        return BoundMethodHandle.bindSingle(mt, lf, narg); // Use known fast path.
    +    }
    +    @Override
    +    /*non-public*/ final BoundMethodHandle copyWithExtendI(MethodType mt, LambdaForm lf, int narg) {
    +        try {
    +            return (BoundMethodHandle) SPECIES_DATA.extendWith(I_TYPE).constructor().invokeBasic(mt, lf, narg);
    +        } catch (Throwable ex) {
    +            throw uncaughtException(ex);
    +        }
    +    }
    +    @Override
    +    /*non-public*/ final BoundMethodHandle copyWithExtendJ(MethodType mt, LambdaForm lf, long narg) {
    +        try {
    +            return (BoundMethodHandle) SPECIES_DATA.extendWith(J_TYPE).constructor().invokeBasic(mt, lf, narg);
    +        } catch (Throwable ex) {
    +            throw uncaughtException(ex);
    +        }
    +    }
    +    @Override
    +    /*non-public*/ final BoundMethodHandle copyWithExtendF(MethodType mt, LambdaForm lf, float narg) {
    +        try {
    +            return (BoundMethodHandle) SPECIES_DATA.extendWith(F_TYPE).constructor().invokeBasic(mt, lf, narg);
    +        } catch (Throwable ex) {
    +            throw uncaughtException(ex);
    +        }
    +    }
    +    @Override
    +    /*non-public*/ final BoundMethodHandle copyWithExtendD(MethodType mt, LambdaForm lf, double narg) {
    +        try {
    +            return (BoundMethodHandle) SPECIES_DATA.extendWith(D_TYPE).constructor().invokeBasic(mt, lf, narg);
    +        } catch (Throwable ex) {
    +            throw uncaughtException(ex);
    +        }
         }
     }
    diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java b/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
    index f85ab432388..01a074f36e0 100644
    --- a/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
    +++ b/jdk/src/java.base/share/classes/java/lang/reflect/AccessibleObject.java
    @@ -78,7 +78,7 @@ public class AccessibleObject implements AnnotatedElement {
          * object is a {@link Constructor} object for the class {@link
          * java.lang.Class}).  In the event of such a SecurityException, the
          * accessibility of objects is set to {@code flag} for array elements
    -     * upto (and excluding) the element for which the exception occurred; the
    +     * up to (and excluding) the element for which the exception occurred; the
          * accessibility of elements beyond (and including) the element for which
          * the exception occurred is unchanged.
          *
    diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java b/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java
    index f424deec74a..b86e1a4eae0 100644
    --- a/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java
    +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Constructor.java
    @@ -94,8 +94,19 @@ public final class Constructor extends Executable {
         // For sharing of ConstructorAccessors. This branching structure
         // is currently only two levels deep (i.e., one root Constructor
         // and potentially many Constructor objects pointing to it.)
    +    //
    +    // If this branching structure would ever contain cycles, deadlocks can
    +    // occur in annotation code.
         private Constructor      root;
     
    +    /**
    +     * Used by Excecutable for annotation sharing.
    +     */
    +    @Override
    +    Executable getRoot() {
    +        return root;
    +    }
    +
         /**
          * Package-private constructor used by ReflectAccess to enable
          * instantiation of these objects in Java code from the java.lang
    @@ -132,6 +143,9 @@ public final class Constructor extends Executable {
             // which implicitly requires that new java.lang.reflect
             // objects be fabricated for each reflective call on Class
             // objects.)
    +        if (this.root != null)
    +            throw new IllegalArgumentException("Can not copy a non-root Constructor");
    +
             Constructor res = new Constructor<>(clazz,
                                                    parameterTypes,
                                                    exceptionTypes, modifiers, slot,
    @@ -544,15 +558,33 @@ public final class Constructor extends Executable {
          */
         @Override
         public AnnotatedType getAnnotatedReceiverType() {
    -        if (getDeclaringClass().getEnclosingClass() == null)
    -            return super.getAnnotatedReceiverType();
    +        Class thisDeclClass = getDeclaringClass();
    +        Class enclosingClass = thisDeclClass.getEnclosingClass();
     
    +        if (enclosingClass == null) {
    +            // A Constructor for a top-level class
    +            return null;
    +        }
    +
    +        Class outerDeclaringClass = thisDeclClass.getDeclaringClass();
    +        if (outerDeclaringClass == null) {
    +            // A constructor for a local or anonymous class
    +            return null;
    +        }
    +
    +        // Either static nested or inner class
    +        if (Modifier.isStatic(thisDeclClass.getModifiers())) {
    +            // static nested
    +            return null;
    +        }
    +
    +        // A Constructor for an inner class
             return TypeAnnotationParser.buildAnnotatedType(getTypeAnnotationBytes0(),
                     sun.misc.SharedSecrets.getJavaLangAccess().
    -                        getConstantPool(getDeclaringClass()),
    +                    getConstantPool(thisDeclClass),
                     this,
    -                getDeclaringClass(),
    -                getDeclaringClass().getEnclosingClass(),
    +                thisDeclClass,
    +                enclosingClass,
                     TypeAnnotation.TypeAnnotationTarget.METHOD_RECEIVER);
         }
     }
    diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java b/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java
    index 8493d10eaa4..15c6574d078 100644
    --- a/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java
    +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Executable.java
    @@ -52,6 +52,11 @@ public abstract class Executable extends AccessibleObject
          */
         abstract byte[] getAnnotationBytes();
     
    +    /**
    +     * Accessor method to allow code sharing
    +     */
    +    abstract Executable getRoot();
    +
         /**
          * Does the Executable have generic information.
          */
    @@ -540,11 +545,16 @@ public abstract class Executable extends AccessibleObject
     
         private synchronized  Map, Annotation> declaredAnnotations() {
             if (declaredAnnotations == null) {
    -            declaredAnnotations = AnnotationParser.parseAnnotations(
    -                getAnnotationBytes(),
    -                sun.misc.SharedSecrets.getJavaLangAccess().
    -                getConstantPool(getDeclaringClass()),
    -                getDeclaringClass());
    +            Executable root = getRoot();
    +            if (root != null) {
    +                declaredAnnotations = root.declaredAnnotations();
    +            } else {
    +                declaredAnnotations = AnnotationParser.parseAnnotations(
    +                    getAnnotationBytes(),
    +                    sun.misc.SharedSecrets.getJavaLangAccess().
    +                    getConstantPool(getDeclaringClass()),
    +                    getDeclaringClass());
    +            }
             }
             return declaredAnnotations;
         }
    @@ -585,21 +595,24 @@ public abstract class Executable extends AccessibleObject
         /**
          * Returns an {@code AnnotatedType} object that represents the use of a
          * type to specify the receiver type of the method/constructor represented
    -     * by this Executable object. The receiver type of a method/constructor is
    -     * available only if the method/constructor has a receiver
    -     * parameter (JLS 8.4.1).
    +     * by this {@code Executable} object.
          *
    -     * If this {@code Executable} object represents a constructor or instance
    -     * method that does not have a receiver parameter, or has a receiver
    -     * parameter with no annotations on its type, then the return value is an
    -     * {@code AnnotatedType} object representing an element with no
    +     * The receiver type of a method/constructor is available only if the
    +     * method/constructor has a receiver parameter (JLS 8.4.1). If this {@code
    +     * Executable} object represents an instance method or represents a
    +     * constructor of an inner member class, and the
    +     * method/constructor either has no receiver parameter or has a
    +     * receiver parameter with no annotations on its type, then the return
    +     * value is an {@code AnnotatedType} object representing an element with no
          * annotations.
          *
    -     * If this {@code Executable} object represents a static method, then the
    -     * return value is null.
    +     * If this {@code Executable} object represents a static method or
    +     * represents a constructor of a top level, static member, local, or
    +     * anoymous class, then the return value is null.
          *
          * @return an object representing the receiver type of the method or
    -     * constructor represented by this {@code Executable}
    +     * constructor represented by this {@code Executable} or {@code null} if
    +     * this {@code Executable} can not have a receiver parameter
          */
         public AnnotatedType getAnnotatedReceiverType() {
             if (Modifier.isStatic(this.getModifiers()))
    diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Field.java b/jdk/src/java.base/share/classes/java/lang/reflect/Field.java
    index 6e243bc82b6..bb23b22dc94 100644
    --- a/jdk/src/java.base/share/classes/java/lang/reflect/Field.java
    +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Field.java
    @@ -81,6 +81,9 @@ class Field extends AccessibleObject implements Member {
         // For sharing of FieldAccessors. This branching structure is
         // currently only two levels deep (i.e., one root Field and
         // potentially many Field objects pointing to it.)
    +    //
    +    // If this branching structure would ever contain cycles, deadlocks can
    +    // occur in annotation code.
         private Field               root;
     
         // Generics infrastructure
    @@ -141,6 +144,9 @@ class Field extends AccessibleObject implements Member {
             // which implicitly requires that new java.lang.reflect
             // objects be fabricated for each reflective call on Class
             // objects.)
    +        if (this.root != null)
    +            throw new IllegalArgumentException("Can not copy a non-root Field");
    +
             Field res = new Field(clazz, name, type, modifiers, slot, signature, annotations);
             res.root = this;
             // Might as well eagerly propagate this if already present
    @@ -1137,10 +1143,15 @@ class Field extends AccessibleObject implements Member {
     
         private synchronized  Map, Annotation> declaredAnnotations() {
             if (declaredAnnotations == null) {
    -            declaredAnnotations = AnnotationParser.parseAnnotations(
    -                annotations, sun.misc.SharedSecrets.getJavaLangAccess().
    -                getConstantPool(getDeclaringClass()),
    -                getDeclaringClass());
    +            Field root = this.root;
    +            if (root != null) {
    +                declaredAnnotations = root.declaredAnnotations();
    +            } else {
    +                declaredAnnotations = AnnotationParser.parseAnnotations(
    +                        annotations,
    +                        sun.misc.SharedSecrets.getJavaLangAccess().getConstantPool(getDeclaringClass()),
    +                        getDeclaringClass());
    +            }
             }
             return declaredAnnotations;
         }
    diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Method.java b/jdk/src/java.base/share/classes/java/lang/reflect/Method.java
    index 6c58138ee52..ddf0f3888ab 100644
    --- a/jdk/src/java.base/share/classes/java/lang/reflect/Method.java
    +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Method.java
    @@ -79,6 +79,9 @@ public final class Method extends Executable {
         // For sharing of MethodAccessors. This branching structure is
         // currently only two levels deep (i.e., one root Method and
         // potentially many Method objects pointing to it.)
    +    //
    +    // If this branching structure would ever contain cycles, deadlocks can
    +    // occur in annotation code.
         private Method              root;
     
         // Generics infrastructure
    @@ -144,6 +147,9 @@ public final class Method extends Executable {
             // which implicitly requires that new java.lang.reflect
             // objects be fabricated for each reflective call on Class
             // objects.)
    +        if (this.root != null)
    +            throw new IllegalArgumentException("Can not copy a non-root Method");
    +
             Method res = new Method(clazz, name, parameterTypes, returnType,
                                     exceptionTypes, modifiers, slot, signature,
                                     annotations, parameterAnnotations, annotationDefault);
    @@ -153,6 +159,14 @@ public final class Method extends Executable {
             return res;
         }
     
    +    /**
    +     * Used by Excecutable for annotation sharing.
    +     */
    +    @Override
    +    Executable getRoot() {
    +        return root;
    +    }
    +
         @Override
         boolean hasGenericInformation() {
             return (getGenericSignature() != null);
    diff --git a/jdk/src/java.base/share/classes/java/lang/reflect/Parameter.java b/jdk/src/java.base/share/classes/java/lang/reflect/Parameter.java
    index f035b8e5e73..69c568f09fe 100644
    --- a/jdk/src/java.base/share/classes/java/lang/reflect/Parameter.java
    +++ b/jdk/src/java.base/share/classes/java/lang/reflect/Parameter.java
    @@ -173,7 +173,7 @@ public final class Parameter implements AnnotatedElement {
          *         a name.
          */
         public String getName() {
    -        // Note: empty strings as paramete names are now outlawed.
    +        // Note: empty strings as parameter names are now outlawed.
             // The .equals("") is for compatibility with current JVM
             // behavior.  It may be removed at some point.
             if(name == null || name.equals(""))
    diff --git a/jdk/src/java.base/share/classes/java/net/InetAddress.java b/jdk/src/java.base/share/classes/java/net/InetAddress.java
    index 09b645d4d85..eb72c091285 100644
    --- a/jdk/src/java.base/share/classes/java/net/InetAddress.java
    +++ b/jdk/src/java.base/share/classes/java/net/InetAddress.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved.
      * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      *
      * This code is free software; you can redistribute it and/or modify it
    @@ -25,11 +25,8 @@
     
     package java.net;
     
    -import java.util.HashMap;
    -import java.util.LinkedHashMap;
    -import java.util.Random;
    +import java.util.NavigableSet;
     import java.util.Iterator;
    -import java.util.LinkedList;
     import java.util.List;
     import java.util.ArrayList;
     import java.util.ServiceLoader;
    @@ -41,6 +38,11 @@ import java.io.ObjectInputStream;
     import java.io.ObjectInputStream.GetField;
     import java.io.ObjectOutputStream;
     import java.io.ObjectOutputStream.PutField;
    +import java.util.concurrent.ConcurrentHashMap;
    +import java.util.concurrent.ConcurrentMap;
    +import java.util.concurrent.ConcurrentSkipListSet;
    +import java.util.concurrent.atomic.AtomicLong;
    +
     import sun.security.action.*;
     import sun.net.InetAddressCachePolicy;
     import sun.net.util.IPAddressUtil;
    @@ -705,195 +707,130 @@ class InetAddress implements java.io.Serializable {
                 + "/" + getHostAddress();
         }
     
    -    /*
    -     * Cached addresses - our own litle nis, not!
    -     */
    -    private static Cache addressCache = new Cache(Cache.Type.Positive);
    +    // mapping from host name to Addresses - either NameServiceAddresses (while
    +    // still being looked-up by NameService(s)) or CachedAddresses when cached
    +    private static final ConcurrentMap cache =
    +        new ConcurrentHashMap<>();
     
    -    private static Cache negativeCache = new Cache(Cache.Type.Negative);
    +    // CachedAddresses that have to expire are kept ordered in this NavigableSet
    +    // which is scanned on each access
    +    private static final NavigableSet expirySet =
    +        new ConcurrentSkipListSet<>();
     
    -    private static boolean addressCacheInit = false;
    +    // common interface
    +    private interface Addresses {
    +        InetAddress[] get() throws UnknownHostException;
    +    }
     
    -    static InetAddress[]    unknown_array; // put THIS in cache
    +    // a holder for cached addresses with required metadata
    +    private static final class CachedAddresses  implements Addresses, Comparable {
    +        private static final AtomicLong seq = new AtomicLong();
    +        final String host;
    +        final InetAddress[] inetAddresses;
    +        final long expiryTime; // time of expiry (in terms of System.nanoTime())
    +        final long id = seq.incrementAndGet(); // each instance is unique
    +
    +        CachedAddresses(String host, InetAddress[] inetAddresses, long expiryTime) {
    +            this.host = host;
    +            this.inetAddresses = inetAddresses;
    +            this.expiryTime = expiryTime;
    +        }
    +
    +        @Override
    +        public InetAddress[] get() throws UnknownHostException {
    +            if (inetAddresses == null) {
    +                throw new UnknownHostException(host);
    +            }
    +            return inetAddresses;
    +        }
    +
    +        @Override
    +        public int compareTo(CachedAddresses other) {
    +            // natural order is expiry time -
    +            // compare difference of expiry times rather than
    +            // expiry times directly, to avoid possible overflow.
    +            // (see System.nanoTime() recommendations...)
    +            long diff = this.expiryTime - other.expiryTime;
    +            if (diff < 0L) return -1;
    +            if (diff > 0L) return 1;
    +            // ties are broken using unique id
    +            return Long.compare(this.id, other.id);
    +        }
    +    }
    +
    +    // a name service lookup based Addresses implementation which replaces itself
    +    // in cache when the result is obtained
    +    private static final class NameServiceAddresses implements Addresses {
    +        private final String host;
    +        private final InetAddress reqAddr;
    +
    +        NameServiceAddresses(String host, InetAddress reqAddr) {
    +            this.host = host;
    +            this.reqAddr = reqAddr;
    +        }
    +
    +        @Override
    +        public InetAddress[] get() throws UnknownHostException {
    +            Addresses addresses;
    +            // only one thread is doing lookup to name service
    +            // for particular host at any time.
    +            synchronized (this) {
    +                // re-check that we are still us + re-install us if slot empty
    +                addresses = cache.putIfAbsent(host, this);
    +                if (addresses == null) {
    +                    // this can happen when we were replaced by CachedAddresses in
    +                    // some other thread, then CachedAddresses expired and were
    +                    // removed from cache while we were waiting for lock...
    +                    addresses = this;
    +                }
    +                // still us ?
    +                if (addresses == this) {
    +                    // lookup name services
    +                    InetAddress[] inetAddresses;
    +                    UnknownHostException ex;
    +                    int cachePolicy;
    +                    try {
    +                        inetAddresses = getAddressesFromNameService(host, reqAddr);
    +                        ex = null;
    +                        cachePolicy = InetAddressCachePolicy.get();
    +                    } catch (UnknownHostException uhe) {
    +                        inetAddresses = null;
    +                        ex = uhe;
    +                        cachePolicy = InetAddressCachePolicy.getNegative();
    +                    }
    +                    // remove or replace us with cached addresses according to cachePolicy
    +                    if (cachePolicy == InetAddressCachePolicy.NEVER) {
    +                        cache.remove(host, this);
    +                    } else {
    +                        CachedAddresses cachedAddresses = new CachedAddresses(
    +                            host,
    +                            inetAddresses,
    +                            cachePolicy == InetAddressCachePolicy.FOREVER
    +                            ? 0L
    +                            // cachePolicy is in [s] - we need [ns]
    +                            : System.nanoTime() + 1000_000_000L * cachePolicy
    +                        );
    +                        if (cache.replace(host, this, cachedAddresses) &&
    +                            cachePolicy != InetAddressCachePolicy.FOREVER) {
    +                            // schedule expiry
    +                            expirySet.add(cachedAddresses);
    +                        }
    +                    }
    +                    if (inetAddresses == null) {
    +                        throw ex == null ? new UnknownHostException(host) : ex;
    +                    }
    +                    return inetAddresses;
    +                }
    +                // else addresses != this
    +            }
    +            // delegate to different addresses when we are already replaced
    +            // but outside of synchronized block to avoid any chance of dead-locking
    +            return addresses.get();
    +        }
    +    }
     
         static InetAddressImpl  impl;
     
    -    private static final HashMap lookupTable = new HashMap<>();
    -
    -    /**
    -     * Represents a cache entry
    -     */
    -    static final class CacheEntry {
    -
    -        CacheEntry(InetAddress[] addresses, long expiration) {
    -            this.addresses = addresses;
    -            this.expiration = expiration;
    -        }
    -
    -        InetAddress[] addresses;
    -        long expiration;
    -    }
    -
    -    /**
    -     * A cache that manages entries based on a policy specified
    -     * at creation time.
    -     */
    -    static final class Cache {
    -        private LinkedHashMap cache;
    -        private Type type;
    -
    -        enum Type {Positive, Negative};
    -
    -        /**
    -         * Create cache
    -         */
    -        public Cache(Type type) {
    -            this.type = type;
    -            cache = new LinkedHashMap();
    -        }
    -
    -        private int getPolicy() {
    -            if (type == Type.Positive) {
    -                return InetAddressCachePolicy.get();
    -            } else {
    -                return InetAddressCachePolicy.getNegative();
    -            }
    -        }
    -
    -        /**
    -         * Add an entry to the cache. If there's already an
    -         * entry then for this host then the entry will be
    -         * replaced.
    -         */
    -        public Cache put(String host, InetAddress[] addresses) {
    -            int policy = getPolicy();
    -            if (policy == InetAddressCachePolicy.NEVER) {
    -                return this;
    -            }
    -
    -            // purge any expired entries
    -
    -            if (policy != InetAddressCachePolicy.FOREVER) {
    -
    -                // As we iterate in insertion order we can
    -                // terminate when a non-expired entry is found.
    -                LinkedList expired = new LinkedList<>();
    -                long now = System.currentTimeMillis();
    -                for (String key : cache.keySet()) {
    -                    CacheEntry entry = cache.get(key);
    -
    -                    if (entry.expiration >= 0 && entry.expiration < now) {
    -                        expired.add(key);
    -                    } else {
    -                        break;
    -                    }
    -                }
    -
    -                for (String key : expired) {
    -                    cache.remove(key);
    -                }
    -            }
    -
    -            // create new entry and add it to the cache
    -            // -- as a HashMap replaces existing entries we
    -            //    don't need to explicitly check if there is
    -            //    already an entry for this host.
    -            long expiration;
    -            if (policy == InetAddressCachePolicy.FOREVER) {
    -                expiration = -1;
    -            } else {
    -                expiration = System.currentTimeMillis() + (policy * 1000);
    -            }
    -            CacheEntry entry = new CacheEntry(addresses, expiration);
    -            cache.put(host, entry);
    -            return this;
    -        }
    -
    -        /**
    -         * Query the cache for the specific host. If found then
    -         * return its CacheEntry, or null if not found.
    -         */
    -        public CacheEntry get(String host) {
    -            int policy = getPolicy();
    -            if (policy == InetAddressCachePolicy.NEVER) {
    -                return null;
    -            }
    -            CacheEntry entry = cache.get(host);
    -
    -            // check if entry has expired
    -            if (entry != null && policy != InetAddressCachePolicy.FOREVER) {
    -                if (entry.expiration >= 0 &&
    -                    entry.expiration < System.currentTimeMillis()) {
    -                    cache.remove(host);
    -                    entry = null;
    -                }
    -            }
    -
    -            return entry;
    -        }
    -    }
    -
    -    /*
    -     * Initialize cache and insert anyLocalAddress into the
    -     * unknown array with no expiry.
    -     */
    -    private static void cacheInitIfNeeded() {
    -        assert Thread.holdsLock(addressCache);
    -        if (addressCacheInit) {
    -            return;
    -        }
    -        unknown_array = new InetAddress[1];
    -        unknown_array[0] = impl.anyLocalAddress();
    -
    -        addressCache.put(impl.anyLocalAddress().getHostName(),
    -                         unknown_array);
    -
    -        addressCacheInit = true;
    -    }
    -
    -    /*
    -     * Cache the given hostname and addresses.
    -     */
    -    private static void cacheAddresses(String hostname,
    -                                       InetAddress[] addresses,
    -                                       boolean success) {
    -        hostname = hostname.toLowerCase();
    -        synchronized (addressCache) {
    -            cacheInitIfNeeded();
    -            if (success) {
    -                addressCache.put(hostname, addresses);
    -            } else {
    -                negativeCache.put(hostname, addresses);
    -            }
    -        }
    -    }
    -
    -    /*
    -     * Lookup hostname in cache (positive & negative cache). If
    -     * found return addresses, null if not found.
    -     */
    -    private static InetAddress[] getCachedAddresses(String hostname) {
    -        hostname = hostname.toLowerCase();
    -
    -        // search both positive & negative caches
    -
    -        synchronized (addressCache) {
    -            cacheInitIfNeeded();
    -
    -            CacheEntry entry = addressCache.get(hostname);
    -            if (entry == null) {
    -                entry = negativeCache.get(hostname);
    -            }
    -
    -            if (entry != null) {
    -                return entry.addresses;
    -            }
    -        }
    -
    -        // not found
    -        return null;
    -    }
    -
         private static NameService createNSProvider(String provider) {
             if (provider == null)
                 return null;
    @@ -1168,7 +1105,7 @@ class InetAddress implements java.io.Serializable {
                 // We were expecting an IPv6 Litteral, but got something else
                 throw new UnknownHostException("["+host+"]");
             }
    -        return getAllByName0(host, reqAddr, true);
    +        return getAllByName0(host, reqAddr, true, true);
         }
     
         /**
    @@ -1229,14 +1166,27 @@ class InetAddress implements java.io.Serializable {
          */
         static InetAddress[] getAllByName0 (String host, boolean check)
             throws UnknownHostException  {
    -        return getAllByName0 (host, null, check);
    +        return getAllByName0 (host, null, check, true);
         }
     
    -    private static InetAddress[] getAllByName0 (String host, InetAddress reqAddr, boolean check)
    +    /**
    +     * Designated lookup method.
    +     *
    +     * @param host host name to look up
    +     * @param reqAddr requested address to be the 1st in returned array
    +     * @param check perform security check
    +     * @param useCache use cached value if not expired else always
    +     *                 perform name service lookup (and cache the result)
    +     * @return array of InetAddress(es)
    +     * @throws UnknownHostException if host name is not found
    +     */
    +    private static InetAddress[] getAllByName0(String host,
    +                                               InetAddress reqAddr,
    +                                               boolean check,
    +                                               boolean useCache)
             throws UnknownHostException  {
     
             /* If it gets here it is presumed to be a hostname */
    -        /* Cache.get can return: null, unknownAddress, or InetAddress[] */
     
             /* make sure the connection to the host is allowed, before we
              * give out a hostname
    @@ -1248,155 +1198,106 @@ class InetAddress implements java.io.Serializable {
                 }
             }
     
    -        InetAddress[] addresses = getCachedAddresses(host);
    -
    -        /* If no entry in cache, then do the host lookup */
    -        if (addresses == null) {
    -            addresses = getAddressesFromNameService(host, reqAddr);
    +        // remove expired addresses from cache - expirySet keeps them ordered
    +        // by expiry time so we only need to iterate the prefix of the NavigableSet...
    +        long now = System.nanoTime();
    +        for (CachedAddresses caddrs : expirySet) {
    +            // compare difference of time instants rather than
    +            // time instants directly, to avoid possible overflow.
    +            // (see System.nanoTime() recommendations...)
    +            if ((caddrs.expiryTime - now) < 0L) {
    +                // ConcurrentSkipListSet uses weakly consistent iterator,
    +                // so removing while iterating is OK...
    +                if (expirySet.remove(caddrs)) {
    +                    // ... remove from cache
    +                    cache.remove(caddrs.host, caddrs);
    +                }
    +            } else {
    +                // we encountered 1st element that expires in future
    +                break;
    +            }
             }
     
    -        if (addresses == unknown_array)
    -            throw new UnknownHostException(host);
    +        // look-up or remove from cache
    +        Addresses addrs;
    +        if (useCache) {
    +            addrs = cache.get(host);
    +        } else {
    +            addrs = cache.remove(host);
    +            if (addrs != null) {
    +                if (addrs instanceof CachedAddresses) {
    +                    // try removing from expirySet too if CachedAddresses
    +                    expirySet.remove(addrs);
    +                }
    +                addrs = null;
    +            }
    +        }
     
    -        return addresses.clone();
    +        if (addrs == null) {
    +            // create a NameServiceAddresses instance which will look up
    +            // the name service and install it within cache...
    +            Addresses oldAddrs = cache.putIfAbsent(
    +                host,
    +                addrs = new NameServiceAddresses(host, reqAddr)
    +            );
    +            if (oldAddrs != null) { // lost putIfAbsent race
    +                addrs = oldAddrs;
    +            }
    +        }
    +
    +        // ask Addresses to get an array of InetAddress(es) and clone it
    +        return addrs.get().clone();
         }
     
    -    private static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr)
    +    static InetAddress[] getAddressesFromNameService(String host, InetAddress reqAddr)
             throws UnknownHostException
         {
             InetAddress[] addresses = null;
    -        boolean success = false;
             UnknownHostException ex = null;
     
    -        // Check whether the host is in the lookupTable.
    -        // 1) If the host isn't in the lookupTable when
    -        //    checkLookupTable() is called, checkLookupTable()
    -        //    would add the host in the lookupTable and
    -        //    return null. So we will do the lookup.
    -        // 2) If the host is in the lookupTable when
    -        //    checkLookupTable() is called, the current thread
    -        //    would be blocked until the host is removed
    -        //    from the lookupTable. Then this thread
    -        //    should try to look up the addressCache.
    -        //     i) if it found the addresses in the
    -        //        addressCache, checkLookupTable()  would
    -        //        return the addresses.
    -        //     ii) if it didn't find the addresses in the
    -        //         addressCache for any reason,
    -        //         it should add the host in the
    -        //         lookupTable and return null so the
    -        //         following code would do  a lookup itself.
    -        if ((addresses = checkLookupTable(host)) == null) {
    +        for (NameService nameService : nameServices) {
                 try {
    -                // This is the first thread which looks up the addresses
    -                // this host or the cache entry for this host has been
    -                // expired so this thread should do the lookup.
    -                for (NameService nameService : nameServices) {
    -                    try {
    -                        /*
    -                         * Do not put the call to lookup() inside the
    -                         * constructor.  if you do you will still be
    -                         * allocating space when the lookup fails.
    -                         */
    -
    -                        addresses = nameService.lookupAllHostAddr(host);
    -                        success = true;
    -                        break;
    -                    } catch (UnknownHostException uhe) {
    -                        if (host.equalsIgnoreCase("localhost")) {
    -                            InetAddress[] local = new InetAddress[] { impl.loopbackAddress() };
    -                            addresses = local;
    -                            success = true;
    -                            break;
    -                        }
    -                        else {
    -                            addresses = unknown_array;
    -                            success = false;
    -                            ex = uhe;
    -                        }
    -                    }
    +                addresses = nameService.lookupAllHostAddr(host);
    +                break;
    +            } catch (UnknownHostException uhe) {
    +                if (host.equalsIgnoreCase("localhost")) {
    +                    addresses = new InetAddress[] { impl.loopbackAddress() };
    +                    break;
                     }
    -
    -                // More to do?
    -                if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) {
    -                    // Find it?
    -                    int i = 1;
    -                    for (; i < addresses.length; i++) {
    -                        if (addresses[i].equals(reqAddr)) {
    -                            break;
    -                        }
    -                    }
    -                    // Rotate
    -                    if (i < addresses.length) {
    -                        InetAddress tmp, tmp2 = reqAddr;
    -                        for (int j = 0; j < i; j++) {
    -                            tmp = addresses[j];
    -                            addresses[j] = tmp2;
    -                            tmp2 = tmp;
    -                        }
    -                        addresses[i] = tmp2;
    -                    }
    -                }
    -                // Cache the address.
    -                cacheAddresses(host, addresses, success);
    -
    -                if (!success && ex != null)
    -                    throw ex;
    -
    -            } finally {
    -                // Delete host from the lookupTable and notify
    -                // all threads waiting on the lookupTable monitor.
    -                updateLookupTable(host);
    -            }
    -        }
    -
    -        return addresses;
    -    }
    -
    -
    -    private static InetAddress[] checkLookupTable(String host) {
    -        synchronized (lookupTable) {
    -            // If the host isn't in the lookupTable, add it in the
    -            // lookuptable and return null. The caller should do
    -            // the lookup.
    -            if (lookupTable.containsKey(host) == false) {
    -                lookupTable.put(host, null);
    -                return null;
    -            }
    -
    -            // If the host is in the lookupTable, it means that another
    -            // thread is trying to look up the addresses of this host.
    -            // This thread should wait.
    -            while (lookupTable.containsKey(host)) {
    -                try {
    -                    lookupTable.wait();
    -                } catch (InterruptedException e) {
    +                else {
    +                    ex = uhe;
                     }
                 }
             }
     
    -        // The other thread has finished looking up the addresses of
    -        // the host. This thread should retry to get the addresses
    -        // from the addressCache. If it doesn't get the addresses from
    -        // the cache, it will try to look up the addresses itself.
    -        InetAddress[] addresses = getCachedAddresses(host);
             if (addresses == null) {
    -            synchronized (lookupTable) {
    -                lookupTable.put(host, null);
    -                return null;
    +            throw ex == null ? new UnknownHostException(host) : ex;
    +        }
    +
    +        // More to do?
    +        if (reqAddr != null && addresses.length > 1 && !addresses[0].equals(reqAddr)) {
    +            // Find it?
    +            int i = 1;
    +            for (; i < addresses.length; i++) {
    +                if (addresses[i].equals(reqAddr)) {
    +                    break;
    +                }
    +            }
    +            // Rotate
    +            if (i < addresses.length) {
    +                InetAddress tmp, tmp2 = reqAddr;
    +                for (int j = 0; j < i; j++) {
    +                    tmp = addresses[j];
    +                    addresses[j] = tmp2;
    +                    tmp2 = tmp;
    +                }
    +                addresses[i] = tmp2;
                 }
             }
     
             return addresses;
         }
     
    -    private static void updateLookupTable(String host) {
    -        synchronized (lookupTable) {
    -            lookupTable.remove(host);
    -            lookupTable.notifyAll();
    -        }
    -    }
    -
         /**
          * Returns an {@code InetAddress} object given the raw IP address .
          * The argument is in network byte order: the highest order
    @@ -1418,10 +1319,18 @@ class InetAddress implements java.io.Serializable {
             return getByAddress(null, addr);
         }
     
    -    private static InetAddress cachedLocalHost = null;
    -    private static long cacheTime = 0;
    -    private static final long maxCacheTime = 5000L;
    -    private static final Object cacheLock = new Object();
    +    private static final class CachedLocalHost {
    +        final String host;
    +        final InetAddress addr;
    +        final long expiryTime = System.nanoTime() + 5000_000_000L; // now + 5s;
    +
    +        CachedLocalHost(String host, InetAddress addr) {
    +            this.host = host;
    +            this.addr = addr;
    +        }
    +    }
    +
    +    private static volatile CachedLocalHost cachedLocalHost;
     
         /**
          * Returns the address of the local host. This is achieved by retrieving
    @@ -1450,47 +1359,41 @@ class InetAddress implements java.io.Serializable {
     
             SecurityManager security = System.getSecurityManager();
             try {
    +            // is cached data still valid?
    +            CachedLocalHost clh = cachedLocalHost;
    +            if (clh != null && (clh.expiryTime - System.nanoTime()) >= 0L) {
    +                if (security != null) {
    +                    security.checkConnect(clh.host, -1);
    +                }
    +                return clh.addr;
    +            }
    +
                 String local = impl.getLocalHostName();
     
                 if (security != null) {
                     security.checkConnect(local, -1);
                 }
     
    +            InetAddress localAddr;
                 if (local.equals("localhost")) {
    -                return impl.loopbackAddress();
    -            }
    -
    -            InetAddress ret = null;
    -            synchronized (cacheLock) {
    -                long now = System.currentTimeMillis();
    -                if (cachedLocalHost != null) {
    -                    if ((now - cacheTime) < maxCacheTime) // Less than 5s old?
    -                        ret = cachedLocalHost;
    -                    else
    -                        cachedLocalHost = null;
    -                }
    -
    -                // we are calling getAddressesFromNameService directly
    -                // to avoid getting localHost from cache
    -                if (ret == null) {
    -                    InetAddress[] localAddrs;
    -                    try {
    -                        localAddrs =
    -                            InetAddress.getAddressesFromNameService(local, null);
    -                    } catch (UnknownHostException uhe) {
    -                        // Rethrow with a more informative error message.
    -                        UnknownHostException uhe2 =
    -                            new UnknownHostException(local + ": " +
    -                                                     uhe.getMessage());
    -                        uhe2.initCause(uhe);
    -                        throw uhe2;
    -                    }
    -                    cachedLocalHost = localAddrs[0];
    -                    cacheTime = now;
    -                    ret = localAddrs[0];
    +                // shortcut for "localhost" host name
    +                localAddr = impl.loopbackAddress();
    +            } else {
    +                // call getAllByName0 without security checks and
    +                // without using cached data
    +                try {
    +                    localAddr = getAllByName0(local, null, false, false)[0];
    +                } catch (UnknownHostException uhe) {
    +                    // Rethrow with a more informative error message.
    +                    UnknownHostException uhe2 =
    +                        new UnknownHostException(local + ": " +
    +                                                 uhe.getMessage());
    +                    uhe2.initCause(uhe);
    +                    throw uhe2;
                     }
                 }
    -            return ret;
    +            cachedLocalHost = new CachedLocalHost(local, localAddr);
    +            return localAddr;
             } catch (java.lang.SecurityException e) {
                 return impl.loopbackAddress();
             }
    diff --git a/jdk/src/java.base/share/classes/java/net/NetPermission.java b/jdk/src/java.base/share/classes/java/net/NetPermission.java
    index 9178f348723..dad3fb99f32 100644
    --- a/jdk/src/java.base/share/classes/java/net/NetPermission.java
    +++ b/jdk/src/java.base/share/classes/java/net/NetPermission.java
    @@ -72,10 +72,10 @@ import java.util.StringTokenizer;
      *   
      *
      * 
    - *  getNetworkInformation
    - *  The ability to retrieve all information about local network interfaces.
    - *  Malicious code can read information about network hardware such as
    - *  MAC addresses, which could be used to construct local IPv6 addresses.
    + *   getNetworkInformation
    + *   The ability to retrieve all information about local network interfaces.
    + *   Malicious code can read information about network hardware such as
    + *   MAC addresses, which could be used to construct local IPv6 addresses.
      * 
      *
      * 
    @@ -98,8 +98,8 @@ import java.util.StringTokenizer;
      * 
      *   requestPasswordAuthentication
      *   The ability
    - * to ask the authenticator registered with the system for
    - * a password
    + *   to ask the authenticator registered with the system for
    + *   a password
      *   Malicious code may steal this password.
      * 
      *
    @@ -116,11 +116,11 @@ import java.util.StringTokenizer;
      * 
      *   setDefaultAuthenticator
      *   The ability to set the
    - * way authentication information is retrieved when
    - * a proxy or HTTP server asks for authentication
    + *   way authentication information is retrieved when
    + *   a proxy or HTTP server asks for authentication
      *   Malicious
    - * code can set an authenticator that monitors and steals user
    - * authentication input as it retrieves the input from the user.
    + *   code can set an authenticator that monitors and steals user
    + *   authentication input as it retrieves the input from the user.
      * 
      *
      * 
    @@ -143,13 +143,13 @@ import java.util.StringTokenizer;
      * 
      *   specifyStreamHandler
      *   The ability
    - * to specify a stream handler when constructing a URL
    + *   to specify a stream handler when constructing a URL
      *   Malicious code may create a URL with resources that it would
    -normally not have access to (like file:/foo/fum/), specifying a
    -stream handler that gets the actual bytes from someplace it does
    -have access to. Thus it might be able to trick the system into
    -creating a ProtectionDomain/CodeSource for a class even though
    -that class really didn't come from that location.
    + *   normally not have access to (like file:/foo/fum/), specifying a
    + *   stream handler that gets the actual bytes from someplace it does
    + *   have access to. Thus it might be able to trick the system into
    + *   creating a ProtectionDomain/CodeSource for a class even though
    + *   that class really didn't come from that location.
      * 
      * 
      *
    diff --git a/jdk/src/java.base/share/classes/java/net/SocketInputStream.java b/jdk/src/java.base/share/classes/java/net/SocketInputStream.java
    index 224051ff608..41b18bdc7e0 100644
    --- a/jdk/src/java.base/share/classes/java/net/SocketInputStream.java
    +++ b/jdk/src/java.base/share/classes/java/net/SocketInputStream.java
    @@ -96,6 +96,26 @@ class SocketInputStream extends FileInputStream
                                        int timeout)
             throws IOException;
     
    +    // wrap native call to allow instrumentation
    +    /**
    +     * Reads into an array of bytes at the specified offset using
    +     * the received socket primitive.
    +     * @param fd the FileDescriptor
    +     * @param b the buffer into which the data is read
    +     * @param off the start offset of the data
    +     * @param len the maximum number of bytes read
    +     * @param timeout the read timeout in ms
    +     * @return the actual number of bytes read, -1 is
    +     *          returned when the end of the stream is reached.
    +     * @exception IOException If an I/O error has occurred.
    +     */
    +    private int socketRead(FileDescriptor fd,
    +                           byte b[], int off, int len,
    +                           int timeout)
    +        throws IOException {
    +        return socketRead0(fd, b, off, len, timeout);
    +    }
    +
         /**
          * Reads into a byte array data from the socket.
          * @param b the buffer into which the data is read
    @@ -147,7 +167,7 @@ class SocketInputStream extends FileInputStream
             // acquire file descriptor and do the read
             FileDescriptor fd = impl.acquireFD();
             try {
    -            n = socketRead0(fd, b, off, length, timeout);
    +            n = socketRead(fd, b, off, length, timeout);
                 if (n > 0) {
                     return n;
                 }
    @@ -165,7 +185,7 @@ class SocketInputStream extends FileInputStream
                 impl.setConnectionResetPending();
                 impl.acquireFD();
                 try {
    -                n = socketRead0(fd, b, off, length, timeout);
    +                n = socketRead(fd, b, off, length, timeout);
                     if (n > 0) {
                         return n;
                     }
    diff --git a/jdk/src/java.base/share/classes/java/net/SocketPermission.java b/jdk/src/java.base/share/classes/java/net/SocketPermission.java
    index 1f3248077be..8894152512b 100644
    --- a/jdk/src/java.base/share/classes/java/net/SocketPermission.java
    +++ b/jdk/src/java.base/share/classes/java/net/SocketPermission.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1997, 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
    @@ -30,6 +30,7 @@ import java.util.Vector;
     import java.util.List;
     import java.util.ArrayList;
     import java.util.Collections;
    +import java.util.StringJoiner;
     import java.util.StringTokenizer;
     import java.net.InetAddress;
     import java.security.Permission;
    @@ -1112,36 +1113,21 @@ public final class SocketPermission extends Permission
          * @param mask a specific integer action mask to translate into a string
          * @return the canonical string representation of the actions
          */
    -    private static String getActions(int mask)
    -    {
    -        StringBuilder sb = new StringBuilder();
    -        boolean comma = false;
    -
    +    private static String getActions(int mask) {
    +        StringJoiner sj = new StringJoiner(",");
             if ((mask & CONNECT) == CONNECT) {
    -            comma = true;
    -            sb.append("connect");
    +            sj.add("connect");
             }
    -
             if ((mask & LISTEN) == LISTEN) {
    -            if (comma) sb.append(',');
    -            else comma = true;
    -            sb.append("listen");
    +            sj.add("listen");
             }
    -
             if ((mask & ACCEPT) == ACCEPT) {
    -            if (comma) sb.append(',');
    -            else comma = true;
    -            sb.append("accept");
    +            sj.add("accept");
             }
    -
    -
             if ((mask & RESOLVE) == RESOLVE) {
    -            if (comma) sb.append(',');
    -            else comma = true;
    -            sb.append("resolve");
    +            sj.add("resolve");
             }
    -
    -        return sb.toString();
    +        return sj.toString();
         }
     
         /**
    diff --git a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
    index e448a120bdc..7bb5fc54a9e 100644
    --- a/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
    +++ b/jdk/src/java.base/share/classes/java/net/URLClassLoader.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1997, 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
    @@ -354,10 +354,11 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
          * @exception NullPointerException if {@code name} is {@code null}.
          */
         protected Class findClass(final String name)
    -         throws ClassNotFoundException
    +        throws ClassNotFoundException
         {
    +        final Class result;
             try {
    -            return AccessController.doPrivileged(
    +            result = AccessController.doPrivileged(
                     new PrivilegedExceptionAction>() {
                         public Class run() throws ClassNotFoundException {
                             String path = name.replace('.', '/').concat(".class");
    @@ -369,13 +370,17 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
                                     throw new ClassNotFoundException(name, e);
                                 }
                             } else {
    -                            throw new ClassNotFoundException(name);
    +                            return null;
                             }
                         }
                     }, acc);
             } catch (java.security.PrivilegedActionException pae) {
                 throw (ClassNotFoundException) pae.getException();
             }
    +        if (result == null) {
    +            throw new ClassNotFoundException(name);
    +        }
    +        return result;
         }
     
         /*
    @@ -407,6 +412,29 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
             return pkg;
         }
     
    +    // Also called by VM to define Package for classes loaded from the CDS
    +    // archive
    +    private void definePackageInternal(String pkgname, Manifest man, URL url)
    +    {
    +        if (getAndVerifyPackage(pkgname, man, url) == null) {
    +            try {
    +                if (man != null) {
    +                    definePackage(pkgname, man, url);
    +                } else {
    +                    definePackage(pkgname, null, null, null, null, null, null, null);
    +                }
    +            } catch (IllegalArgumentException iae) {
    +                // parallel-capable class loaders: re-verify in case of a
    +                // race condition
    +                if (getAndVerifyPackage(pkgname, man, url) == null) {
    +                    // Should never happen
    +                    throw new AssertionError("Cannot find package " +
    +                                             pkgname);
    +                }
    +            }
    +        }
    +    }
    +
         /*
          * Defines a Class using the class bytes obtained from the specified
          * Resource. The resulting Class must be resolved before it can be
    @@ -420,23 +448,7 @@ public class URLClassLoader extends SecureClassLoader implements Closeable {
                 String pkgname = name.substring(0, i);
                 // Check if package already loaded.
                 Manifest man = res.getManifest();
    -            if (getAndVerifyPackage(pkgname, man, url) == null) {
    -                try {
    -                    if (man != null) {
    -                        definePackage(pkgname, man, url);
    -                    } else {
    -                        definePackage(pkgname, null, null, null, null, null, null, null);
    -                    }
    -                } catch (IllegalArgumentException iae) {
    -                    // parallel-capable class loaders: re-verify in case of a
    -                    // race condition
    -                    if (getAndVerifyPackage(pkgname, man, url) == null) {
    -                        // Should never happen
    -                        throw new AssertionError("Cannot find package " +
    -                                                 pkgname);
    -                    }
    -                }
    -            }
    +            definePackageInternal(pkgname, man, url);
             }
             // Now read the class bytes and define the class
             java.nio.ByteBuffer bb = res.getByteBuffer();
    diff --git a/jdk/src/java.base/share/classes/java/security/SecureRandom.java b/jdk/src/java.base/share/classes/java/security/SecureRandom.java
    index b9ae7220b38..0accb4cc7a4 100644
    --- a/jdk/src/java.base/share/classes/java/security/SecureRandom.java
    +++ b/jdk/src/java.base/share/classes/java/security/SecureRandom.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 1996, 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
    @@ -39,15 +39,16 @@ import sun.security.jca.GetInstance.Instance;
      *
      * 

    A cryptographically strong random number * minimally complies with the statistical random number generator tests - * specified in + * specified in + * * FIPS 140-2, Security Requirements for Cryptographic Modules, * section 4.9.1. * Additionally, SecureRandom must produce non-deterministic output. * Therefore any seed material passed to a SecureRandom object must be * unpredictable, and all SecureRandom output sequences must be * cryptographically strong, as described in - * - * RFC 1750: Randomness Recommendations for Security. + * + * RFC 4086: Randomness Requirements for Security. * *

    A caller obtains a SecureRandom instance via the * no-argument constructor or one of the {@code getInstance} methods: diff --git a/jdk/src/java.base/share/classes/java/text/CalendarBuilder.java b/jdk/src/java.base/share/classes/java/text/CalendarBuilder.java index a8246b676ca..cb30a358ea4 100644 --- a/jdk/src/java.base/share/classes/java/text/CalendarBuilder.java +++ b/jdk/src/java.base/share/classes/java/text/CalendarBuilder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -26,6 +26,7 @@ package java.text; import java.util.Calendar; +import java.util.StringJoiner; import static java.util.GregorianCalendar.*; /** @@ -146,19 +147,13 @@ class CalendarBuilder { } public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append("CalendarBuilder:["); + StringJoiner sj = new StringJoiner(",", "CalendarBuilder:[", "]"); for (int i = 0; i < field.length; i++) { if (isSet(i)) { - sb.append(i).append('=').append(field[MAX_FIELD + i]).append(','); + sj.add(i + "=" + field[MAX_FIELD + i]); } } - int lastIndex = sb.length() - 1; - if (sb.charAt(lastIndex) == ',') { - sb.setLength(lastIndex); - } - sb.append(']'); - return sb.toString(); + return sj.toString(); } static int toISODayOfWeek(int calendarDayOfWeek) { diff --git a/jdk/src/java.base/share/classes/java/time/Duration.java b/jdk/src/java.base/share/classes/java/time/Duration.java index cb672c4d3b4..d5a49956e90 100644 --- a/jdk/src/java.base/share/classes/java/time/Duration.java +++ b/jdk/src/java.base/share/classes/java/time/Duration.java @@ -388,19 +388,21 @@ public final class Duration Matcher matcher = PATTERN.matcher(text); if (matcher.matches()) { // check for letter T but no time sections - if ("T".equals(matcher.group(3)) == false) { - boolean negate = "-".equals(matcher.group(1)); - String dayMatch = matcher.group(2); - String hourMatch = matcher.group(4); - String minuteMatch = matcher.group(5); - String secondMatch = matcher.group(6); - String fractionMatch = matcher.group(7); - if (dayMatch != null || hourMatch != null || minuteMatch != null || secondMatch != null) { - long daysAsSecs = parseNumber(text, dayMatch, SECONDS_PER_DAY, "days"); - long hoursAsSecs = parseNumber(text, hourMatch, SECONDS_PER_HOUR, "hours"); - long minsAsSecs = parseNumber(text, minuteMatch, SECONDS_PER_MINUTE, "minutes"); - long seconds = parseNumber(text, secondMatch, 1, "seconds"); - int nanos = parseFraction(text, fractionMatch, seconds < 0 ? -1 : 1); + if (!charMatch(text, matcher.start(3), matcher.end(3), 'T')) { + boolean negate = charMatch(text, matcher.start(1), matcher.end(1), '-'); + + int dayStart = matcher.start(2), dayEnd = matcher.end(2); + int hourStart = matcher.start(4), hourEnd = matcher.end(4); + int minuteStart = matcher.start(5), minuteEnd = matcher.end(5); + int secondStart = matcher.start(6), secondEnd = matcher.end(6); + int fractionStart = matcher.start(7), fractionEnd = matcher.end(7); + + if (dayStart >= 0 || hourStart >= 0 || minuteStart >= 0 || secondStart >= 0) { + long daysAsSecs = parseNumber(text, dayStart, dayEnd, SECONDS_PER_DAY, "days"); + long hoursAsSecs = parseNumber(text, hourStart, hourEnd, SECONDS_PER_HOUR, "hours"); + long minsAsSecs = parseNumber(text, minuteStart, minuteEnd, SECONDS_PER_MINUTE, "minutes"); + long seconds = parseNumber(text, secondStart, secondEnd, 1, "seconds"); + int nanos = parseFraction(text, fractionStart, fractionEnd, seconds < 0 ? -1 : 1); try { return create(negate, daysAsSecs, hoursAsSecs, minsAsSecs, seconds, nanos); } catch (ArithmeticException ex) { @@ -412,27 +414,37 @@ public final class Duration throw new DateTimeParseException("Text cannot be parsed to a Duration", text, 0); } - private static long parseNumber(CharSequence text, String parsed, int multiplier, String errorText) { + private static boolean charMatch(CharSequence text, int start, int end, char c) { + return (start >= 0 && end == start + 1 && text.charAt(start) == c); + } + + private static long parseNumber(CharSequence text, int start, int end, int multiplier, String errorText) { // regex limits to [-+]?[0-9]+ - if (parsed == null) { + if (start < 0 || end < 0) { return 0; } try { - long val = Long.parseLong(parsed); + long val = Long.parseLong(text, start, end, 10); return Math.multiplyExact(val, multiplier); } catch (NumberFormatException | ArithmeticException ex) { throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: " + errorText, text, 0).initCause(ex); } } - private static int parseFraction(CharSequence text, String parsed, int negate) { + private static int parseFraction(CharSequence text, int start, int end, int negate) { // regex limits to [0-9]{0,9} - if (parsed == null || parsed.length() == 0) { + if (start < 0 || end < 0 || end - start == 0) { return 0; } try { - parsed = (parsed + "000000000").substring(0, 9); - return Integer.parseInt(parsed) * negate; + int fraction = Integer.parseInt(text, start, end, 10); + + // for number strings smaller than 9 digits, interpret as if there + // were trailing zeros + for (int i = end - start; i < 9; i++) { + fraction *= 10; + } + return fraction * negate; } catch (NumberFormatException | ArithmeticException ex) { throw (DateTimeParseException) new DateTimeParseException("Text cannot be parsed to a Duration: fraction", text, 0).initCause(ex); } diff --git a/jdk/src/java.base/share/classes/java/time/Period.java b/jdk/src/java.base/share/classes/java/time/Period.java index 5d808a42b41..c7c04435262 100644 --- a/jdk/src/java.base/share/classes/java/time/Period.java +++ b/jdk/src/java.base/share/classes/java/time/Period.java @@ -329,17 +329,17 @@ public final class Period Objects.requireNonNull(text, "text"); Matcher matcher = PATTERN.matcher(text); if (matcher.matches()) { - int negate = ("-".equals(matcher.group(1)) ? -1 : 1); - String yearMatch = matcher.group(2); - String monthMatch = matcher.group(3); - String weekMatch = matcher.group(4); - String dayMatch = matcher.group(5); - if (yearMatch != null || monthMatch != null || dayMatch != null || weekMatch != null) { + int negate = (charMatch(text, matcher.start(1), matcher.end(1), '-') ? -1 : 1); + int yearStart = matcher.start(2), yearEnd = matcher.end(2); + int monthStart = matcher.start(3), monthEnd = matcher.end(3); + int weekStart = matcher.start(4), weekEnd = matcher.end(4); + int dayStart = matcher.start(5), dayEnd = matcher.end(5); + if (yearStart >= 0 || monthStart >= 0 || weekStart >= 0 || dayStart >= 0) { try { - int years = parseNumber(text, yearMatch, negate); - int months = parseNumber(text, monthMatch, negate); - int weeks = parseNumber(text, weekMatch, negate); - int days = parseNumber(text, dayMatch, negate); + int years = parseNumber(text, yearStart, yearEnd, negate); + int months = parseNumber(text, monthStart, monthEnd, negate); + int weeks = parseNumber(text, weekStart, weekEnd, negate); + int days = parseNumber(text, dayStart, dayEnd, negate); days = Math.addExact(days, Math.multiplyExact(weeks, 7)); return create(years, months, days); } catch (NumberFormatException ex) { @@ -350,11 +350,15 @@ public final class Period throw new DateTimeParseException("Text cannot be parsed to a Period", text, 0); } - private static int parseNumber(CharSequence text, String str, int negate) { - if (str == null) { + private static boolean charMatch(CharSequence text, int start, int end, char c) { + return (start >= 0 && end == start + 1 && text.charAt(start) == c); + } + + private static int parseNumber(CharSequence text, int start, int end, int negate) { + if (start < 0 || end < 0) { return 0; } - int val = Integer.parseInt(str); + int val = Integer.parseInt(text, start, end, 10); try { return Math.multiplyExact(val, negate); } catch (ArithmeticException ex) { diff --git a/jdk/src/java.base/share/classes/java/util/Arrays.java b/jdk/src/java.base/share/classes/java/util/Arrays.java index b7b75794ce4..628ce831ab6 100644 --- a/jdk/src/java.base/share/classes/java/util/Arrays.java +++ b/jdk/src/java.base/share/classes/java/util/Arrays.java @@ -3865,7 +3865,7 @@ public class Arrays { @Override public boolean contains(Object o) { - return indexOf(o) != -1; + return indexOf(o) >= 0; } @Override diff --git a/jdk/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java b/jdk/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java index e37374af15f..81b769af01f 100644 --- a/jdk/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java +++ b/jdk/src/java.base/share/classes/java/util/JapaneseImperialCalendar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -38,20 +38,20 @@ import sun.util.calendar.LocalGregorianCalendar; import sun.util.calendar.ZoneInfo; /** - * JapaneseImperialCalendar implements a Japanese + * {@code JapaneseImperialCalendar} implements a Japanese * calendar system in which the imperial era-based year numbering is * supported from the Meiji era. The following are the eras supported * by this calendar system. - *

    
    + * 
    {@code
      * ERA value   Era name    Since (in Gregorian)
      * ------------------------------------------------------
      *     0       N/A         N/A
    - *     1       Meiji       1868-01-01 midnight local time
    - *     2       Taisho      1912-07-30 midnight local time
    - *     3       Showa       1926-12-25 midnight local time
    - *     4       Heisei      1989-01-08 midnight local time
    + *     1       Meiji       1868-01-01T00:00:00 local time
    + *     2       Taisho      1912-07-30T00:00:00 local time
    + *     3       Showa       1926-12-25T00:00:00 local time
    + *     4       Heisei      1989-01-08T00:00:00 local time
      * ------------------------------------------------------
    - * 
    + * }
    * *

    ERA value 0 specifies the years before Meiji and * the Gregorian year values are used. Unlike {@link @@ -63,6 +63,31 @@ import sun.util.calendar.ZoneInfo; * with time differences for applying the era transitions. This * calendar implementation assumes local time for all transitions. * + *

    A new era can be specified using property + * jdk.calendar.japanese.supplemental.era. The new era is added to the + * predefined eras. The syntax of the property is as follows. + *

    + *   {@code name=,abbr=,since=}
    + * 
    + * where + *
    + *
    {@code :}
    the full name of the new era (non-ASCII characters allowed) + *
    {@code :}
    the abbreviation of the new era (non-ASCII characters allowed) + *
    {@code :}
    the start time of the new era represented by + * milliseconds from 1970-01-01T00:00:00 local time or UTC if {@code 'u'} is + * appended to the milliseconds value. (ASCII digits only) + *
    + * + *

    If the given era is invalid, such as the since value before the + * beginning of the last predefined era, the given era will be + * ignored. + * + *

    The following is an example of the property usage. + *

    + *   java -Djdk.calendar.japanese.supplemental.era="name=NewEra,abbr=N,since=253374307200000"
    + * 
    + * The property specifies an era change to NewEra at 9999-02-11T00:00:00 local time. + * * @author Masayoshi Okutsu * @since 1.6 */ @@ -102,7 +127,6 @@ class JapaneseImperialCalendar extends Calendar { public static final int HEISEI = 4; private static final int EPOCH_OFFSET = 719163; // Fixed date of January 1, 1970 (Gregorian) - private static final int EPOCH_YEAR = 1970; // Useful millisecond constants. Although ONE_DAY and ONE_WEEK can fit // into ints, they must be longs in order to prevent arithmetic overflow @@ -111,7 +135,6 @@ class JapaneseImperialCalendar extends Calendar { private static final int ONE_MINUTE = 60*ONE_SECOND; private static final int ONE_HOUR = 60*ONE_MINUTE; private static final long ONE_DAY = 24*ONE_HOUR; - private static final long ONE_WEEK = 7*ONE_DAY; // Reference to the sun.util.calendar.LocalGregorianCalendar instance (singleton). private static final LocalGregorianCalendar jcal @@ -217,6 +240,7 @@ class JapaneseImperialCalendar extends Calendar { }; // Proclaim serialization compatibility with JDK 1.6 + @SuppressWarnings("FieldNameHidesFieldInSuperclass") private static final long serialVersionUID = -3364572813905467929L; static { @@ -340,6 +364,7 @@ class JapaneseImperialCalendar extends Calendar { * false otherwise. * @see Calendar#compareTo(Calendar) */ + @Override public boolean equals(Object obj) { return obj instanceof JapaneseImperialCalendar && super.equals(obj); @@ -349,6 +374,7 @@ class JapaneseImperialCalendar extends Calendar { * Generates the hash code for this * JapaneseImperialCalendar object. */ + @Override public int hashCode() { return super.hashCode() ^ jdate.hashCode(); } @@ -381,6 +407,7 @@ class JapaneseImperialCalendar extends Calendar { * or if any calendar fields have out-of-range values in * non-lenient mode. */ + @Override public void add(int field, int amount) { // If amount == 0, do nothing even the given field is out of // range. This is tested by JCK. @@ -509,6 +536,7 @@ class JapaneseImperialCalendar extends Calendar { } } + @Override public void roll(int field, boolean up) { roll(field, up ? +1 : -1); } @@ -533,6 +561,7 @@ class JapaneseImperialCalendar extends Calendar { * @see #add(int,int) * @see #set(int,int) */ + @Override public void roll(int field, int amount) { // If amount == 0, do nothing even the given field is out of // range. This is tested by JCK. diff --git a/jdk/src/java.base/share/classes/java/util/LinkedList.java b/jdk/src/java.base/share/classes/java/util/LinkedList.java index 18a8b21ba80..343ded84d07 100644 --- a/jdk/src/java.base/share/classes/java/util/LinkedList.java +++ b/jdk/src/java.base/share/classes/java/util/LinkedList.java @@ -314,7 +314,7 @@ public class LinkedList * @return {@code true} if this list contains the specified element */ public boolean contains(Object o) { - return indexOf(o) != -1; + return indexOf(o) >= 0; } /** diff --git a/jdk/src/java.base/share/classes/java/util/Locale.java b/jdk/src/java.base/share/classes/java/util/Locale.java index fbcb2f75e66..cf29686e693 100644 --- a/jdk/src/java.base/share/classes/java/util/Locale.java +++ b/jdk/src/java.base/share/classes/java/util/Locale.java @@ -2059,14 +2059,11 @@ public final class Locale implements Cloneable, Serializable { // If we have no list patterns, compose the list in a simple, // non-localized way. if (listPattern == null || listCompositionPattern == null) { - StringBuilder result = new StringBuilder(); + StringJoiner sj = new StringJoiner(","); for (int i = 0; i < stringList.length; ++i) { - if (i > 0) { - result.append(','); - } - result.append(stringList[i]); + sj.add(stringList[i]); } - return result.toString(); + return sj.toString(); } // Compose the list down to three elements if necessary diff --git a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java index b0fb9816be0..cc1af05aa36 100644 --- a/jdk/src/java.base/share/classes/java/util/PriorityQueue.java +++ b/jdk/src/java.base/share/classes/java/util/PriorityQueue.java @@ -406,7 +406,7 @@ public class PriorityQueue extends AbstractQueue * @return {@code true} if this queue contains the specified element */ public boolean contains(Object o) { - return indexOf(o) != -1; + return indexOf(o) >= 0; } /** diff --git a/jdk/src/java.base/share/classes/java/util/PropertyPermission.java b/jdk/src/java.base/share/classes/java/util/PropertyPermission.java index d532bddabf6..7e818a90b64 100644 --- a/jdk/src/java.base/share/classes/java/util/PropertyPermission.java +++ b/jdk/src/java.base/share/classes/java/util/PropertyPermission.java @@ -324,20 +324,16 @@ public final class PropertyPermission extends BasicPermission { * @return the canonical string representation of the actions. */ static String getActions(int mask) { - StringBuilder sb = new StringBuilder(); - boolean comma = false; - - if ((mask & READ) == READ) { - comma = true; - sb.append("read"); + switch (mask & (READ|WRITE)) { + case READ: + return SecurityConstants.PROPERTY_READ_ACTION; + case WRITE: + return SecurityConstants.PROPERTY_WRITE_ACTION; + case READ|WRITE: + return SecurityConstants.PROPERTY_RW_ACTION; + default: + return ""; } - - if ((mask & WRITE) == WRITE) { - if (comma) sb.append(','); - else comma = true; - sb.append("write"); - } - return sb.toString(); } /** diff --git a/jdk/src/java.base/share/classes/java/util/StringJoiner.java b/jdk/src/java.base/share/classes/java/util/StringJoiner.java index b6ba84c5df8..b08a2f9b711 100644 --- a/jdk/src/java.base/share/classes/java/util/StringJoiner.java +++ b/jdk/src/java.base/share/classes/java/util/StringJoiner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -24,6 +24,9 @@ */ package java.util; +import sun.misc.JavaLangAccess; +import sun.misc.SharedSecrets; + /** * {@code StringJoiner} is used to construct a sequence of characters separated * by a delimiter and optionally starting with a supplied prefix @@ -67,22 +70,24 @@ public final class StringJoiner { private final String delimiter; private final String suffix; - /* - * StringBuilder value -- at any time, the characters constructed from the - * prefix, the added element separated by the delimiter, but without the - * suffix, so that we can more easily add elements without having to jigger - * the suffix each time. - */ - private StringBuilder value; + /** Contains all the string components added so far. */ + private String[] elts; - /* - * By default, the string consisting of prefix+suffix, returned by - * toString(), or properties of value, when no elements have yet been added, - * i.e. when it is empty. This may be overridden by the user to be some - * other value including the empty String. + /** The number of string components added so far. */ + private int size; + + /** Total length in chars so far, excluding prefix and suffix. */ + private int len; + + /** + * When overriden by the user to be non-null via {@link setEmptyValue}, the + * string returned by toString() when no elements have yet been added. + * When null, prefix + suffix is used as the empty value. */ private String emptyValue; + private static final JavaLangAccess jla = SharedSecrets.getJavaLangAccess(); + /** * Constructs a {@code StringJoiner} with no characters in it, with no * {@code prefix} or {@code suffix}, and a copy of the supplied @@ -125,7 +130,6 @@ public final class StringJoiner { this.prefix = prefix.toString(); this.delimiter = delimiter.toString(); this.suffix = suffix.toString(); - this.emptyValue = this.prefix + this.suffix; } /** @@ -148,29 +152,44 @@ public final class StringJoiner { return this; } + private static int getChars(String s, char[] chars, int start) { + int len = s.length(); + s.getChars(0, len, chars, start); + return len; + } + /** * Returns the current value, consisting of the {@code prefix}, the values * added so far separated by the {@code delimiter}, and the {@code suffix}, * unless no elements have been added in which case, the - * {@code prefix + suffix} or the {@code emptyValue} characters are returned + * {@code prefix + suffix} or the {@code emptyValue} characters are returned. * * @return the string representation of this {@code StringJoiner} */ @Override public String toString() { - if (value == null) { + final String[] elts = this.elts; + if (elts == null && emptyValue != null) { return emptyValue; - } else { - if (suffix.equals("")) { - return value.toString(); - } else { - int initialLength = value.length(); - String result = value.append(suffix).toString(); - // reset value to pre-append initialLength - value.setLength(initialLength); - return result; + } + final int size = this.size; + final int addLen = prefix.length() + suffix.length(); + if (addLen == 0) { + compactElts(); + return size == 0 ? "" : elts[0]; + } + final String delimiter = this.delimiter; + final char[] chars = new char[len + addLen]; + int k = getChars(prefix, chars, 0); + if (size > 0) { + k += getChars(elts[0], chars, k); + for (int i = 1; i < size; i++) { + k += getChars(delimiter, chars, k); + k += getChars(elts[i], chars, k); } } + k += getChars(suffix, chars, k); + return jla.newStringUnsafe(chars); } /** @@ -182,7 +201,16 @@ public final class StringJoiner { * @return a reference to this {@code StringJoiner} */ public StringJoiner add(CharSequence newElement) { - prepareBuilder().append(newElement); + final String elt = String.valueOf(newElement); + if (elts == null) { + elts = new String[8]; + } else { + if (size == elts.length) + elts = Arrays.copyOf(elts, 2 * size); + len += delimiter.length(); + } + len += elt.length(); + elts[size++] = elt; return this; } @@ -207,24 +235,25 @@ public final class StringJoiner { */ public StringJoiner merge(StringJoiner other) { Objects.requireNonNull(other); - if (other.value != null) { - final int length = other.value.length(); - // lock the length so that we can seize the data to be appended - // before initiate copying to avoid interference, especially when - // merge 'this' - StringBuilder builder = prepareBuilder(); - builder.append(other.value, other.prefix.length(), length); + if (other.elts == null) { + return this; } - return this; + other.compactElts(); + return add(other.elts[0]); } - private StringBuilder prepareBuilder() { - if (value != null) { - value.append(delimiter); - } else { - value = new StringBuilder().append(prefix); + private void compactElts() { + if (size > 1) { + final char[] chars = new char[len]; + int i = 1, k = getChars(elts[0], chars, 0); + do { + k += getChars(delimiter, chars, k); + k += getChars(elts[i], chars, k); + elts[i] = null; + } while (++i < size); + size = 1; + elts[0] = jla.newStringUnsafe(chars); } - return value; } /** @@ -238,10 +267,7 @@ public final class StringJoiner { * @return the length of the current value of {@code StringJoiner} */ public int length() { - // Remember that we never actually append the suffix unless we return - // the full (present) value or some sub-string or length of it, so that - // we can add on more if we need to. - return (value != null ? value.length() + suffix.length() : - emptyValue.length()); + return (size == 0 && emptyValue != null) ? emptyValue.length() : + len + prefix.length() + suffix.length(); } } diff --git a/jdk/src/java.base/share/classes/java/util/UUID.java b/jdk/src/java.base/share/classes/java/util/UUID.java index 11e024678e0..39e507df40c 100644 --- a/jdk/src/java.base/share/classes/java/util/UUID.java +++ b/jdk/src/java.base/share/classes/java/util/UUID.java @@ -194,7 +194,8 @@ public final class UUID implements java.io.Serializable, Comparable { * */ public static UUID fromString(String name) { - if (name.length() > 36) { + int len = name.length(); + if (len > 36) { throw new IllegalArgumentException("UUID string too large"); } @@ -214,15 +215,14 @@ public final class UUID implements java.io.Serializable, Comparable { throw new IllegalArgumentException("Invalid UUID string: " + name); } - long mostSigBits = Long.parseLong(name, 16, 0, dash1) & 0xffffffffL; + long mostSigBits = Long.parseLong(name, 0, dash1, 16) & 0xffffffffL; mostSigBits <<= 16; - mostSigBits |= Long.parseLong(name, 16, dash1 + 1, dash2) & 0xffffL; + mostSigBits |= Long.parseLong(name, dash1 + 1, dash2, 16) & 0xffffL; mostSigBits <<= 16; - mostSigBits |= Long.parseLong(name, 16, dash2 + 1, dash3) & 0xffffL; - - long leastSigBits = Long.parseLong(name, 16, dash3 + 1, dash4) & 0xffffL; + mostSigBits |= Long.parseLong(name, dash2 + 1, dash3, 16) & 0xffffL; + long leastSigBits = Long.parseLong(name, dash3 + 1, dash4, 16) & 0xffffL; leastSigBits <<= 48; - leastSigBits |= Long.parseLong(name, 16, dash4 + 1) & 0xffffffffffffL; + leastSigBits |= Long.parseLong(name, dash4 + 1, len, 16) & 0xffffffffffffL; return new UUID(mostSigBits, leastSigBits); } diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java index 9e89169e15f..8476dcc1237 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletableFuture.java @@ -50,7 +50,6 @@ import java.util.concurrent.TimeoutException; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletionException; import java.util.concurrent.CompletionStage; -import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.locks.LockSupport; /** @@ -77,9 +76,9 @@ import java.util.concurrent.locks.LockSupport; *
  • All async methods without an explicit Executor * argument are performed using the {@link ForkJoinPool#commonPool()} * (unless it does not support a parallelism level of at least two, in - * which case, a new Thread is used). To simplify monitoring, - * debugging, and tracking, all generated asynchronous tasks are - * instances of the marker interface {@link + * which case, a new Thread is created to run each task). To simplify + * monitoring, debugging, and tracking, all generated asynchronous + * tasks are instances of the marker interface {@link * AsynchronousCompletionTask}.
  • * *
  • All CompletionStage methods are implemented independently of @@ -113,141 +112,1556 @@ public class CompletableFuture implements Future, CompletionStage { /* * Overview: * - * 1. Non-nullness of field result (set via CAS) indicates done. - * An AltResult is used to box null as a result, as well as to - * hold exceptions. Using a single field makes completion fast - * and simple to detect and trigger, at the expense of a lot of - * encoding and decoding that infiltrates many methods. One minor - * simplification relies on the (static) NIL (to box null results) - * being the only AltResult with a null exception field, so we - * don't usually need explicit comparisons with NIL. The CF - * exception propagation mechanics surrounding decoding rely on - * unchecked casts of decoded results really being unchecked, - * where user type errors are caught at point of use, as is - * currently the case in Java. These are highlighted by using - * SuppressWarnings-annotated temporaries. + * A CompletableFuture may have dependent completion actions, + * collected in a linked stack. It atomically completes by CASing + * a result field, and then pops off and runs those actions. This + * applies across normal vs exceptional outcomes, sync vs async + * actions, binary triggers, and various forms of completions. * - * 2. Waiters are held in a Treiber stack similar to the one used - * in FutureTask, Phaser, and SynchronousQueue. See their - * internal documentation for algorithmic details. + * Non-nullness of field result (set via CAS) indicates done. An + * AltResult is used to box null as a result, as well as to hold + * exceptions. Using a single field makes completion simple to + * detect and trigger. Encoding and decoding is straightforward + * but adds to the sprawl of trapping and associating exceptions + * with targets. Minor simplifications rely on (static) NIL (to + * box null results) being the only AltResult with a null + * exception field, so we don't usually need explicit comparisons. + * Even though some of the generics casts are unchecked (see + * SuppressWarnings annotations), they are placed to be + * appropriate even if checked. * - * 3. Completions are also kept in a list/stack, and pulled off - * and run when completion is triggered. (We could even use the - * same stack as for waiters, but would give up the potential - * parallelism obtained because woken waiters help release/run - * others -- see method postComplete). Because post-processing - * may race with direct calls, class Completion opportunistically - * extends AtomicInteger so callers can claim the action via - * compareAndSet(0, 1). The Completion.run methods are all - * written a boringly similar uniform way (that sometimes includes - * unnecessary-looking checks, kept to maintain uniformity). - * There are enough dimensions upon which they differ that - * attempts to factor commonalities while maintaining efficiency - * require more lines of code than they would save. + * Dependent actions are represented by Completion objects linked + * as Treiber stacks headed by field "stack". There are Completion + * classes for each kind of action, grouped into single-input + * (UniCompletion), two-input (BiCompletion), projected + * (BiCompletions using either (not both) of two inputs), shared + * (CoCompletion, used by the second of two sources), zero-input + * source actions, and Signallers that unblock waiters. Class + * Completion extends ForkJoinTask to enable async execution + * (adding no space overhead because we exploit its "tag" methods + * to maintain claims). It is also declared as Runnable to allow + * usage with arbitrary executors. * - * 4. The exported then/and/or methods do support a bit of - * factoring (see doThenApply etc). They must cope with the - * intrinsic races surrounding addition of a dependent action - * versus performing the action directly because the task is - * already complete. For example, a CF may not be complete upon - * entry, so a dependent completion is added, but by the time it - * is added, the target CF is complete, so must be directly - * executed. This is all done while avoiding unnecessary object - * construction in safe-bypass cases. + * Support for each kind of CompletionStage relies on a separate + * class, along with two CompletableFuture methods: + * + * * A Completion class with name X corresponding to function, + * prefaced with "Uni", "Bi", or "Or". Each class contains + * fields for source(s), actions, and dependent. They are + * boringly similar, differing from others only with respect to + * underlying functional forms. We do this so that users don't + * encounter layers of adaptors in common usages. We also + * include "Relay" classes/methods that don't correspond to user + * methods; they copy results from one stage to another. + * + * * Boolean CompletableFuture method x(...) (for example + * uniApply) takes all of the arguments needed to check that an + * action is triggerable, and then either runs the action or + * arranges its async execution by executing its Completion + * argument, if present. The method returns true if known to be + * complete. + * + * * Completion method tryFire(int mode) invokes the associated x + * method with its held arguments, and on success cleans up. + * The mode argument allows tryFire to be called twice (SYNC, + * then ASYNC); the first to screen and trap exceptions while + * arranging to execute, and the second when called from a + * task. (A few classes are not used async so take slightly + * different forms.) The claim() callback suppresses function + * invocation if already claimed by another thread. + * + * * CompletableFuture method xStage(...) is called from a public + * stage method of CompletableFuture x. It screens user + * arguments and invokes and/or creates the stage object. If + * not async and x is already complete, the action is run + * immediately. Otherwise a Completion c is created, pushed to + * x's stack (unless done), and started or triggered via + * c.tryFire. This also covers races possible if x completes + * while pushing. Classes with two inputs (for example BiApply) + * deal with races across both while pushing actions. The + * second completion is a CoCompletion pointing to the first, + * shared so that at most one performs the action. The + * multiple-arity methods allOf and anyOf do this pairwise to + * form trees of completions. + * + * Note that the generic type parameters of methods vary according + * to whether "this" is a source, dependent, or completion. + * + * Method postComplete is called upon completion unless the target + * is guaranteed not to be observable (i.e., not yet returned or + * linked). Multiple threads can call postComplete, which + * atomically pops each dependent action, and tries to trigger it + * via method tryFire, in NESTED mode. Triggering can propagate + * recursively, so NESTED mode returns its completed dependent (if + * one exists) for further processing by its caller (see method + * postFire). + * + * Blocking methods get() and join() rely on Signaller Completions + * that wake up waiting threads. The mechanics are similar to + * Treiber stack wait-nodes used in FutureTask, Phaser, and + * SynchronousQueue. See their internal documentation for + * algorithmic details. + * + * Without precautions, CompletableFutures would be prone to + * garbage accumulation as chains of Completions build up, each + * pointing back to its sources. So we null out fields as soon as + * possible (see especially method Completion.detach). The + * screening checks needed anyway harmlessly ignore null arguments + * that may have been obtained during races with threads nulling + * out fields. We also try to unlink fired Completions from + * stacks that might never be popped (see method postFire). + * Completion fields need not be declared as final or volatile + * because they are only visible to other threads upon safe + * publication. */ - // preliminaries + volatile Object result; // Either the result or boxed AltResult + volatile Completion stack; // Top of Treiber stack of dependent actions - static final class AltResult { - final Throwable ex; // null only for NIL - AltResult(Throwable ex) { this.ex = ex; } + final boolean internalComplete(Object r) { // CAS from null to r + return UNSAFE.compareAndSwapObject(this, RESULT, null, r); } + final boolean casStack(Completion cmp, Completion val) { + return UNSAFE.compareAndSwapObject(this, STACK, cmp, val); + } + + /** Returns true if successfully pushed c onto stack. */ + final boolean tryPushStack(Completion c) { + Completion h = stack; + lazySetNext(c, h); + return UNSAFE.compareAndSwapObject(this, STACK, h, c); + } + + /** Unconditionally pushes c onto stack, retrying if necessary. */ + final void pushStack(Completion c) { + do {} while (!tryPushStack(c)); + } + + /* ------------- Encoding and decoding outcomes -------------- */ + + static final class AltResult { // See above + final Throwable ex; // null only for NIL + AltResult(Throwable x) { this.ex = x; } + } + + /** The encoding of the null value. */ static final AltResult NIL = new AltResult(null); - // Fields + /** Completes with the null value, unless already completed. */ + final boolean completeNull() { + return UNSAFE.compareAndSwapObject(this, RESULT, null, + NIL); + } - volatile Object result; // Either the result or boxed AltResult - volatile WaitNode waiters; // Treiber stack of threads blocked on get() - volatile CompletionNode completions; // list (Treiber stack) of completions + /** Returns the encoding of the given non-exceptional value. */ + final Object encodeValue(T t) { + return (t == null) ? NIL : t; + } - // Basic utilities for triggering and processing completions + /** Completes with a non-exceptional result, unless already completed. */ + final boolean completeValue(T t) { + return UNSAFE.compareAndSwapObject(this, RESULT, null, + (t == null) ? NIL : t); + } /** - * Removes and signals all waiting threads and runs all completions. + * Returns the encoding of the given (non-null) exception as a + * wrapped CompletionException unless it is one already. + */ + static AltResult encodeThrowable(Throwable x) { + return new AltResult((x instanceof CompletionException) ? x : + new CompletionException(x)); + } + + /** Completes with an exceptional result, unless already completed. */ + final boolean completeThrowable(Throwable x) { + return UNSAFE.compareAndSwapObject(this, RESULT, null, + encodeThrowable(x)); + } + + /** + * Returns the encoding of the given (non-null) exception as a + * wrapped CompletionException unless it is one already. May + * return the given Object r (which must have been the result of a + * source future) if it is equivalent, i.e. if this is a simple + * relay of an existing CompletionException. + */ + static Object encodeThrowable(Throwable x, Object r) { + if (!(x instanceof CompletionException)) + x = new CompletionException(x); + else if (r instanceof AltResult && x == ((AltResult)r).ex) + return r; + return new AltResult(x); + } + + /** + * Completes with the given (non-null) exceptional result as a + * wrapped CompletionException unless it is one already, unless + * already completed. May complete with the given Object r + * (which must have been the result of a source future) if it is + * equivalent, i.e. if this is a simple propagation of an + * existing CompletionException. + */ + final boolean completeThrowable(Throwable x, Object r) { + return UNSAFE.compareAndSwapObject(this, RESULT, null, + encodeThrowable(x, r)); + } + + /** + * Returns the encoding of the given arguments: if the exception + * is non-null, encodes as AltResult. Otherwise uses the given + * value, boxed as NIL if null. + */ + Object encodeOutcome(T t, Throwable x) { + return (x == null) ? (t == null) ? NIL : t : encodeThrowable(x); + } + + /** + * Returns the encoding of a copied outcome; if exceptional, + * rewraps as a CompletionException, else returns argument. + */ + static Object encodeRelay(Object r) { + Throwable x; + return (((r instanceof AltResult) && + (x = ((AltResult)r).ex) != null && + !(x instanceof CompletionException)) ? + new AltResult(new CompletionException(x)) : r); + } + + /** + * Completes with r or a copy of r, unless already completed. + * If exceptional, r is first coerced to a CompletionException. + */ + final boolean completeRelay(Object r) { + return UNSAFE.compareAndSwapObject(this, RESULT, null, + encodeRelay(r)); + } + + /** + * Reports result using Future.get conventions. + */ + private static T reportGet(Object r) + throws InterruptedException, ExecutionException { + if (r == null) // by convention below, null means interrupted + throw new InterruptedException(); + if (r instanceof AltResult) { + Throwable x, cause; + if ((x = ((AltResult)r).ex) == null) + return null; + if (x instanceof CancellationException) + throw (CancellationException)x; + if ((x instanceof CompletionException) && + (cause = x.getCause()) != null) + x = cause; + throw new ExecutionException(x); + } + @SuppressWarnings("unchecked") T t = (T) r; + return t; + } + + /** + * Decodes outcome to return result or throw unchecked exception. + */ + private static T reportJoin(Object r) { + if (r instanceof AltResult) { + Throwable x; + if ((x = ((AltResult)r).ex) == null) + return null; + if (x instanceof CancellationException) + throw (CancellationException)x; + if (x instanceof CompletionException) + throw (CompletionException)x; + throw new CompletionException(x); + } + @SuppressWarnings("unchecked") T t = (T) r; + return t; + } + + /* ------------- Async task preliminaries -------------- */ + + /** + * A marker interface identifying asynchronous tasks produced by + * {@code async} methods. This may be useful for monitoring, + * debugging, and tracking asynchronous activities. + * + * @since 1.8 + */ + public static interface AsynchronousCompletionTask { + } + + private static final boolean useCommonPool = + (ForkJoinPool.getCommonPoolParallelism() > 1); + + /** + * Default executor -- ForkJoinPool.commonPool() unless it cannot + * support parallelism. + */ + private static final Executor asyncPool = useCommonPool ? + ForkJoinPool.commonPool() : new ThreadPerTaskExecutor(); + + /** Fallback if ForkJoinPool.commonPool() cannot support parallelism */ + static final class ThreadPerTaskExecutor implements Executor { + public void execute(Runnable r) { new Thread(r).start(); } + } + + /** + * Null-checks user executor argument, and translates uses of + * commonPool to asyncPool in case parallelism disabled. + */ + static Executor screenExecutor(Executor e) { + if (!useCommonPool && e == ForkJoinPool.commonPool()) + return asyncPool; + if (e == null) throw new NullPointerException(); + return e; + } + + // Modes for Completion.tryFire. Signedness matters. + static final int SYNC = 0; + static final int ASYNC = 1; + static final int NESTED = -1; + + /* ------------- Base Completion classes and operations -------------- */ + + @SuppressWarnings("serial") + abstract static class Completion extends ForkJoinTask + implements Runnable, AsynchronousCompletionTask { + volatile Completion next; // Treiber stack link + + /** + * Performs completion action if triggered, returning a + * dependent that may need propagation, if one exists. + * + * @param mode SYNC, ASYNC, or NESTED + */ + abstract CompletableFuture tryFire(int mode); + + /** Returns true if possibly still triggerable. Used by cleanStack. */ + abstract boolean isLive(); + + public final void run() { tryFire(ASYNC); } + public final boolean exec() { tryFire(ASYNC); return true; } + public final Void getRawResult() { return null; } + public final void setRawResult(Void v) {} + } + + static void lazySetNext(Completion c, Completion next) { + UNSAFE.putOrderedObject(c, NEXT, next); + } + + /** + * Pops and tries to trigger all reachable dependents. Call only + * when known to be done. */ final void postComplete() { - WaitNode q; Thread t; - while ((q = waiters) != null) { - if (UNSAFE.compareAndSwapObject(this, WAITERS, q, q.next) && - (t = q.thread) != null) { - q.thread = null; - LockSupport.unpark(t); + /* + * On each step, variable f holds current dependents to pop + * and run. It is extended along only one path at a time, + * pushing others to avoid unbounded recursion. + */ + CompletableFuture f = this; Completion h; + while ((h = f.stack) != null || + (f != this && (h = (f = this).stack) != null)) { + CompletableFuture d; Completion t; + if (f.casStack(h, t = h.next)) { + if (t != null) { + if (f != this) { + pushStack(h); + continue; + } + h.next = null; // detach + } + f = (d = h.tryFire(NESTED)) == null ? this : d; } } + } - CompletionNode h; Completion c; - while ((h = completions) != null) { - if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, h, h.next) && - (c = h.completion) != null) - c.run(); + /** Traverses stack and unlinks dead Completions. */ + final void cleanStack() { + for (Completion p = null, q = stack; q != null;) { + Completion s = q.next; + if (q.isLive()) { + p = q; + q = s; + } + else if (p == null) { + casStack(q, s); + q = stack; + } + else { + p.next = s; + if (p.isLive()) + q = s; + else { + p = null; // restart + q = stack; + } + } + } + } + + /* ------------- One-input Completions -------------- */ + + /** A Completion with a source, dependent, and executor. */ + @SuppressWarnings("serial") + abstract static class UniCompletion extends Completion { + Executor executor; // executor to use (null if none) + CompletableFuture dep; // the dependent to complete + CompletableFuture src; // source for action + + UniCompletion(Executor executor, CompletableFuture dep, + CompletableFuture src) { + this.executor = executor; this.dep = dep; this.src = src; + } + + /** + * Returns true if action can be run. Call only when known to + * be triggerable. Uses FJ tag bit to ensure that only one + * thread claims ownership. If async, starts as task -- a + * later call to tryFire will run action. + */ + final boolean claim() { + Executor e = executor; + if (compareAndSetForkJoinTaskTag((short)0, (short)1)) { + if (e == null) + return true; + executor = null; // disable + e.execute(this); + } + return false; + } + + final boolean isLive() { return dep != null; } + } + + /** Pushes the given completion (if it exists) unless done. */ + final void push(UniCompletion c) { + if (c != null) { + while (result == null && !tryPushStack(c)) + lazySetNext(c, null); // clear on failure } } /** - * Triggers completion with the encoding of the given arguments: - * if the exception is non-null, encodes it as a wrapped - * CompletionException unless it is one already. Otherwise uses - * the given result, boxed as NIL if null. + * Post-processing by dependent after successful UniCompletion + * tryFire. Tries to clean stack of source a, and then either runs + * postComplete or returns this to caller, depending on mode. */ - final void internalComplete(T v, Throwable ex) { + final CompletableFuture postFire(CompletableFuture a, int mode) { + if (a != null && a.stack != null) { + if (mode < 0 || a.result == null) + a.cleanStack(); + else + a.postComplete(); + } + if (result != null && stack != null) { + if (mode < 0) + return this; + else + postComplete(); + } + return null; + } + + @SuppressWarnings("serial") + static final class UniApply extends UniCompletion { + Function fn; + UniApply(Executor executor, CompletableFuture dep, + CompletableFuture src, + Function fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniApply(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); + } + } + + final boolean uniApply(CompletableFuture a, + Function f, + UniApply c) { + Object r; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + tryComplete: if (result == null) { + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; + } + try { + if (c != null && !c.claim()) + return false; + @SuppressWarnings("unchecked") S s = (S) r; + completeValue(f.apply(s)); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture uniApplyStage( + Executor e, Function f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.uniApply(this, f, null)) { + UniApply c = new UniApply(e, d, this, f); + push(c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class UniAccept extends UniCompletion { + Consumer fn; + UniAccept(Executor executor, CompletableFuture dep, + CompletableFuture src, Consumer fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniAccept(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); + } + } + + final boolean uniAccept(CompletableFuture a, + Consumer f, UniAccept c) { + Object r; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + tryComplete: if (result == null) { + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; + } + try { + if (c != null && !c.claim()) + return false; + @SuppressWarnings("unchecked") S s = (S) r; + f.accept(s); + completeNull(); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture uniAcceptStage(Executor e, + Consumer f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.uniAccept(this, f, null)) { + UniAccept c = new UniAccept(e, d, this, f); + push(c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class UniRun extends UniCompletion { + Runnable fn; + UniRun(Executor executor, CompletableFuture dep, + CompletableFuture src, Runnable fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniRun(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); + } + } + + final boolean uniRun(CompletableFuture a, Runnable f, UniRun c) { + Object r; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + if (result == null) { + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) + completeThrowable(x, r); + else + try { + if (c != null && !c.claim()) + return false; + f.run(); + completeNull(); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture uniRunStage(Executor e, Runnable f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.uniRun(this, f, null)) { + UniRun c = new UniRun(e, d, this, f); + push(c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class UniWhenComplete extends UniCompletion { + BiConsumer fn; + UniWhenComplete(Executor executor, CompletableFuture dep, + CompletableFuture src, + BiConsumer fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniWhenComplete(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); + } + } + + final boolean uniWhenComplete(CompletableFuture a, + BiConsumer f, + UniWhenComplete c) { + Object r; T t; Throwable x = null; + if (a == null || (r = a.result) == null || f == null) + return false; + if (result == null) { + try { + if (c != null && !c.claim()) + return false; + if (r instanceof AltResult) { + x = ((AltResult)r).ex; + t = null; + } else { + @SuppressWarnings("unchecked") T tr = (T) r; + t = tr; + } + f.accept(t, x); + if (x == null) { + internalComplete(r); + return true; + } + } catch (Throwable ex) { + if (x == null) + x = ex; + } + completeThrowable(x, r); + } + return true; + } + + private CompletableFuture uniWhenCompleteStage( + Executor e, BiConsumer f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.uniWhenComplete(this, f, null)) { + UniWhenComplete c = new UniWhenComplete(e, d, this, f); + push(c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class UniHandle extends UniCompletion { + BiFunction fn; + UniHandle(Executor executor, CompletableFuture dep, + CompletableFuture src, + BiFunction fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniHandle(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); + } + } + + final boolean uniHandle(CompletableFuture a, + BiFunction f, + UniHandle c) { + Object r; S s; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + if (result == null) { + try { + if (c != null && !c.claim()) + return false; + if (r instanceof AltResult) { + x = ((AltResult)r).ex; + s = null; + } else { + x = null; + @SuppressWarnings("unchecked") S ss = (S) r; + s = ss; + } + completeValue(f.apply(s, x)); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture uniHandleStage( + Executor e, BiFunction f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.uniHandle(this, f, null)) { + UniHandle c = new UniHandle(e, d, this, f); + push(c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class UniExceptionally extends UniCompletion { + Function fn; + UniExceptionally(CompletableFuture dep, CompletableFuture src, + Function fn) { + super(null, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { // never ASYNC + // assert mode != ASYNC; + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || !d.uniExceptionally(a = src, fn, this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); + } + } + + final boolean uniExceptionally(CompletableFuture a, + Function f, + UniExceptionally c) { + Object r; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + if (result == null) { + try { + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) { + if (c != null && !c.claim()) + return false; + completeValue(f.apply(x)); + } else + internalComplete(r); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture uniExceptionallyStage( + Function f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (!d.uniExceptionally(this, f, null)) { + UniExceptionally c = new UniExceptionally(d, this, f); + push(c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class UniRelay extends UniCompletion { // for Compose + UniRelay(CompletableFuture dep, CompletableFuture src) { + super(null, dep, src); + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || !d.uniRelay(a = src)) + return null; + src = null; dep = null; + return d.postFire(a, mode); + } + } + + final boolean uniRelay(CompletableFuture a) { + Object r; + if (a == null || (r = a.result) == null) + return false; + if (result == null) // no need to claim + completeRelay(r); + return true; + } + + @SuppressWarnings("serial") + static final class UniCompose extends UniCompletion { + Function> fn; + UniCompose(Executor executor, CompletableFuture dep, + CompletableFuture src, + Function> fn) { + super(executor, dep, src); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; CompletableFuture a; + if ((d = dep) == null || + !d.uniCompose(a = src, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; fn = null; + return d.postFire(a, mode); + } + } + + final boolean uniCompose( + CompletableFuture a, + Function> f, + UniCompose c) { + Object r; Throwable x; + if (a == null || (r = a.result) == null || f == null) + return false; + tryComplete: if (result == null) { + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; + } + try { + if (c != null && !c.claim()) + return false; + @SuppressWarnings("unchecked") S s = (S) r; + CompletableFuture g = f.apply(s).toCompletableFuture(); + if (g.result == null || !uniRelay(g)) { + UniRelay copy = new UniRelay(this, g); + g.push(copy); + copy.tryFire(SYNC); + if (result == null) + return false; + } + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture uniComposeStage( + Executor e, Function> f) { + if (f == null) throw new NullPointerException(); + Object r; Throwable x; + if (e == null && (r = result) != null) { + // try to return function result directly + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + return new CompletableFuture(encodeThrowable(x, r)); + } + r = null; + } + try { + @SuppressWarnings("unchecked") T t = (T) r; + return f.apply(t).toCompletableFuture(); + } catch (Throwable ex) { + return new CompletableFuture(encodeThrowable(ex)); + } + } + CompletableFuture d = new CompletableFuture(); + UniCompose c = new UniCompose(e, d, this, f); + push(c); + c.tryFire(SYNC); + return d; + } + + /* ------------- Two-input Completions -------------- */ + + /** A Completion for an action with two sources */ + @SuppressWarnings("serial") + abstract static class BiCompletion extends UniCompletion { + CompletableFuture snd; // second source for action + BiCompletion(Executor executor, CompletableFuture dep, + CompletableFuture src, CompletableFuture snd) { + super(executor, dep, src); this.snd = snd; + } + } + + /** A Completion delegating to a BiCompletion */ + @SuppressWarnings("serial") + static final class CoCompletion extends Completion { + BiCompletion base; + CoCompletion(BiCompletion base) { this.base = base; } + final CompletableFuture tryFire(int mode) { + BiCompletion c; CompletableFuture d; + if ((c = base) == null || (d = c.tryFire(mode)) == null) + return null; + base = null; // detach + return d; + } + final boolean isLive() { + BiCompletion c; + return (c = base) != null && c.dep != null; + } + } + + /** Pushes completion to this and b unless both done. */ + final void bipush(CompletableFuture b, BiCompletion c) { + if (c != null) { + Object r; + while ((r = result) == null && !tryPushStack(c)) + lazySetNext(c, null); // clear on failure + if (b != null && b != this && b.result == null) { + Completion q = (r != null) ? c : new CoCompletion(c); + while (b.result == null && !b.tryPushStack(q)) + lazySetNext(q, null); // clear on failure + } + } + } + + /** Post-processing after successful BiCompletion tryFire. */ + final CompletableFuture postFire(CompletableFuture a, + CompletableFuture b, int mode) { + if (b != null && b.stack != null) { // clean second source + if (mode < 0 || b.result == null) + b.cleanStack(); + else + b.postComplete(); + } + return postFire(a, mode); + } + + @SuppressWarnings("serial") + static final class BiApply extends BiCompletion { + BiFunction fn; + BiApply(Executor executor, CompletableFuture dep, + CompletableFuture src, CompletableFuture snd, + BiFunction fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.biApply(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); + } + } + + final boolean biApply(CompletableFuture a, + CompletableFuture b, + BiFunction f, + BiApply c) { + Object r, s; Throwable x; + if (a == null || (r = a.result) == null || + b == null || (s = b.result) == null || f == null) + return false; + tryComplete: if (result == null) { + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; + } + if (s instanceof AltResult) { + if ((x = ((AltResult)s).ex) != null) { + completeThrowable(x, s); + break tryComplete; + } + s = null; + } + try { + if (c != null && !c.claim()) + return false; + @SuppressWarnings("unchecked") R rr = (R) r; + @SuppressWarnings("unchecked") S ss = (S) s; + completeValue(f.apply(rr, ss)); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture biApplyStage( + Executor e, CompletionStage o, + BiFunction f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.biApply(this, b, f, null)) { + BiApply c = new BiApply(e, d, this, b, f); + bipush(b, c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class BiAccept extends BiCompletion { + BiConsumer fn; + BiAccept(Executor executor, CompletableFuture dep, + CompletableFuture src, CompletableFuture snd, + BiConsumer fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.biAccept(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); + } + } + + final boolean biAccept(CompletableFuture a, + CompletableFuture b, + BiConsumer f, + BiAccept c) { + Object r, s; Throwable x; + if (a == null || (r = a.result) == null || + b == null || (s = b.result) == null || f == null) + return false; + tryComplete: if (result == null) { + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; + } + if (s instanceof AltResult) { + if ((x = ((AltResult)s).ex) != null) { + completeThrowable(x, s); + break tryComplete; + } + s = null; + } + try { + if (c != null && !c.claim()) + return false; + @SuppressWarnings("unchecked") R rr = (R) r; + @SuppressWarnings("unchecked") S ss = (S) s; + f.accept(rr, ss); + completeNull(); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture biAcceptStage( + Executor e, CompletionStage o, + BiConsumer f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.biAccept(this, b, f, null)) { + BiAccept c = new BiAccept(e, d, this, b, f); + bipush(b, c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class BiRun extends BiCompletion { + Runnable fn; + BiRun(Executor executor, CompletableFuture dep, + CompletableFuture src, + CompletableFuture snd, + Runnable fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.biRun(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); + } + } + + final boolean biRun(CompletableFuture a, CompletableFuture b, + Runnable f, BiRun c) { + Object r, s; Throwable x; + if (a == null || (r = a.result) == null || + b == null || (s = b.result) == null || f == null) + return false; + if (result == null) { + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) + completeThrowable(x, r); + else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null) + completeThrowable(x, s); + else + try { + if (c != null && !c.claim()) + return false; + f.run(); + completeNull(); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture biRunStage(Executor e, CompletionStage o, + Runnable f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.biRun(this, b, f, null)) { + BiRun c = new BiRun<>(e, d, this, b, f); + bipush(b, c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class BiRelay extends BiCompletion { // for And + BiRelay(CompletableFuture dep, + CompletableFuture src, + CompletableFuture snd) { + super(null, dep, src, snd); + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || !d.biRelay(a = src, b = snd)) + return null; + src = null; snd = null; dep = null; + return d.postFire(a, b, mode); + } + } + + boolean biRelay(CompletableFuture a, CompletableFuture b) { + Object r, s; Throwable x; + if (a == null || (r = a.result) == null || + b == null || (s = b.result) == null) + return false; + if (result == null) { + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) + completeThrowable(x, r); + else if (s instanceof AltResult && (x = ((AltResult)s).ex) != null) + completeThrowable(x, s); + else + completeNull(); + } + return true; + } + + /** Recursively constructs a tree of completions. */ + static CompletableFuture andTree(CompletableFuture[] cfs, + int lo, int hi) { + CompletableFuture d = new CompletableFuture(); + if (lo > hi) // empty + d.result = NIL; + else { + CompletableFuture a, b; + int mid = (lo + hi) >>> 1; + if ((a = (lo == mid ? cfs[lo] : + andTree(cfs, lo, mid))) == null || + (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] : + andTree(cfs, mid+1, hi))) == null) + throw new NullPointerException(); + if (!d.biRelay(a, b)) { + BiRelay c = new BiRelay<>(d, a, b); + a.bipush(b, c); + c.tryFire(SYNC); + } + } + return d; + } + + /* ------------- Projected (Ored) BiCompletions -------------- */ + + /** Pushes completion to this and b unless either done. */ + final void orpush(CompletableFuture b, BiCompletion c) { + if (c != null) { + while ((b == null || b.result == null) && result == null) { + if (tryPushStack(c)) { + if (b != null && b != this && b.result == null) { + Completion q = new CoCompletion(c); + while (result == null && b.result == null && + !b.tryPushStack(q)) + lazySetNext(q, null); // clear on failure + } + break; + } + lazySetNext(c, null); // clear on failure + } + } + } + + @SuppressWarnings("serial") + static final class OrApply extends BiCompletion { + Function fn; + OrApply(Executor executor, CompletableFuture dep, + CompletableFuture src, + CompletableFuture snd, + Function fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.orApply(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); + } + } + + final boolean orApply(CompletableFuture a, + CompletableFuture b, + Function f, + OrApply c) { + Object r; Throwable x; + if (a == null || b == null || + ((r = a.result) == null && (r = b.result) == null) || f == null) + return false; + tryComplete: if (result == null) { + try { + if (c != null && !c.claim()) + return false; + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; + } + @SuppressWarnings("unchecked") R rr = (R) r; + completeValue(f.apply(rr)); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture orApplyStage( + Executor e, CompletionStage o, + Function f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.orApply(this, b, f, null)) { + OrApply c = new OrApply(e, d, this, b, f); + orpush(b, c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class OrAccept extends BiCompletion { + Consumer fn; + OrAccept(Executor executor, CompletableFuture dep, + CompletableFuture src, + CompletableFuture snd, + Consumer fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.orAccept(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); + } + } + + final boolean orAccept(CompletableFuture a, + CompletableFuture b, + Consumer f, + OrAccept c) { + Object r; Throwable x; + if (a == null || b == null || + ((r = a.result) == null && (r = b.result) == null) || f == null) + return false; + tryComplete: if (result == null) { + try { + if (c != null && !c.claim()) + return false; + if (r instanceof AltResult) { + if ((x = ((AltResult)r).ex) != null) { + completeThrowable(x, r); + break tryComplete; + } + r = null; + } + @SuppressWarnings("unchecked") R rr = (R) r; + f.accept(rr); + completeNull(); + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture orAcceptStage( + Executor e, CompletionStage o, Consumer f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.orAccept(this, b, f, null)) { + OrAccept c = new OrAccept(e, d, this, b, f); + orpush(b, c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class OrRun extends BiCompletion { + Runnable fn; + OrRun(Executor executor, CompletableFuture dep, + CompletableFuture src, + CompletableFuture snd, + Runnable fn) { + super(executor, dep, src, snd); this.fn = fn; + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || + !d.orRun(a = src, b = snd, fn, mode > 0 ? null : this)) + return null; + dep = null; src = null; snd = null; fn = null; + return d.postFire(a, b, mode); + } + } + + final boolean orRun(CompletableFuture a, CompletableFuture b, + Runnable f, OrRun c) { + Object r; Throwable x; + if (a == null || b == null || + ((r = a.result) == null && (r = b.result) == null) || f == null) + return false; + if (result == null) { + try { + if (c != null && !c.claim()) + return false; + if (r instanceof AltResult && (x = ((AltResult)r).ex) != null) + completeThrowable(x, r); + else { + f.run(); + completeNull(); + } + } catch (Throwable ex) { + completeThrowable(ex); + } + } + return true; + } + + private CompletableFuture orRunStage(Executor e, CompletionStage o, + Runnable f) { + CompletableFuture b; + if (f == null || (b = o.toCompletableFuture()) == null) + throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + if (e != null || !d.orRun(this, b, f, null)) { + OrRun c = new OrRun<>(e, d, this, b, f); + orpush(b, c); + c.tryFire(SYNC); + } + return d; + } + + @SuppressWarnings("serial") + static final class OrRelay extends BiCompletion { // for Or + OrRelay(CompletableFuture dep, CompletableFuture src, + CompletableFuture snd) { + super(null, dep, src, snd); + } + final CompletableFuture tryFire(int mode) { + CompletableFuture d; + CompletableFuture a; + CompletableFuture b; + if ((d = dep) == null || !d.orRelay(a = src, b = snd)) + return null; + src = null; snd = null; dep = null; + return d.postFire(a, b, mode); + } + } + + final boolean orRelay(CompletableFuture a, CompletableFuture b) { + Object r; + if (a == null || b == null || + ((r = a.result) == null && (r = b.result) == null)) + return false; if (result == null) - UNSAFE.compareAndSwapObject - (this, RESULT, null, - (ex == null) ? (v == null) ? NIL : v : - new AltResult((ex instanceof CompletionException) ? ex : - new CompletionException(ex))); - postComplete(); // help out even if not triggered + completeRelay(r); + return true; } - /** - * If triggered, helps release and/or process completions. - */ - final void helpPostComplete() { - if (result != null) - postComplete(); + /** Recursively constructs a tree of completions. */ + static CompletableFuture orTree(CompletableFuture[] cfs, + int lo, int hi) { + CompletableFuture d = new CompletableFuture(); + if (lo <= hi) { + CompletableFuture a, b; + int mid = (lo + hi) >>> 1; + if ((a = (lo == mid ? cfs[lo] : + orTree(cfs, lo, mid))) == null || + (b = (lo == hi ? a : (hi == mid+1) ? cfs[hi] : + orTree(cfs, mid+1, hi))) == null) + throw new NullPointerException(); + if (!d.orRelay(a, b)) { + OrRelay c = new OrRelay<>(d, a, b); + a.orpush(b, c); + c.tryFire(SYNC); + } + } + return d; } - /* ------------- waiting for completions -------------- */ + /* ------------- Zero-input Async forms -------------- */ - /** Number of processors, for spin control */ - static final int NCPU = Runtime.getRuntime().availableProcessors(); + @SuppressWarnings("serial") + static final class AsyncSupply extends ForkJoinTask + implements Runnable, AsynchronousCompletionTask { + CompletableFuture dep; Supplier fn; + AsyncSupply(CompletableFuture dep, Supplier fn) { + this.dep = dep; this.fn = fn; + } + + public final Void getRawResult() { return null; } + public final void setRawResult(Void v) {} + public final boolean exec() { run(); return true; } + + public void run() { + CompletableFuture d; Supplier f; + if ((d = dep) != null && (f = fn) != null) { + dep = null; fn = null; + if (d.result == null) { + try { + d.completeValue(f.get()); + } catch (Throwable ex) { + d.completeThrowable(ex); + } + } + d.postComplete(); + } + } + } + + static CompletableFuture asyncSupplyStage(Executor e, + Supplier f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + e.execute(new AsyncSupply(d, f)); + return d; + } + + @SuppressWarnings("serial") + static final class AsyncRun extends ForkJoinTask + implements Runnable, AsynchronousCompletionTask { + CompletableFuture dep; Runnable fn; + AsyncRun(CompletableFuture dep, Runnable fn) { + this.dep = dep; this.fn = fn; + } + + public final Void getRawResult() { return null; } + public final void setRawResult(Void v) {} + public final boolean exec() { run(); return true; } + + public void run() { + CompletableFuture d; Runnable f; + if ((d = dep) != null && (f = fn) != null) { + dep = null; fn = null; + if (d.result == null) { + try { + f.run(); + d.completeNull(); + } catch (Throwable ex) { + d.completeThrowable(ex); + } + } + d.postComplete(); + } + } + } + + static CompletableFuture asyncRunStage(Executor e, Runnable f) { + if (f == null) throw new NullPointerException(); + CompletableFuture d = new CompletableFuture(); + e.execute(new AsyncRun(d, f)); + return d; + } + + /* ------------- Signallers -------------- */ /** - * Heuristic spin value for waitingGet() before blocking on - * multiprocessors + * Completion for recording and releasing a waiting thread. This + * class implements ManagedBlocker to avoid starvation when + * blocking actions pile up in ForkJoinPools. */ - static final int SPINS = (NCPU > 1) ? 1 << 8 : 0; - - /** - * Linked nodes to record waiting threads in a Treiber stack. See - * other classes such as Phaser and SynchronousQueue for more - * detailed explanation. This class implements ManagedBlocker to - * avoid starvation when blocking actions pile up in - * ForkJoinPools. - */ - static final class WaitNode implements ForkJoinPool.ManagedBlocker { - long nanos; // wait time if timed - final long deadline; // non-zero if timed + @SuppressWarnings("serial") + static final class Signaller extends Completion + implements ForkJoinPool.ManagedBlocker { + long nanos; // wait time if timed + final long deadline; // non-zero if timed volatile int interruptControl; // > 0: interruptible, < 0: interrupted volatile Thread thread; - volatile WaitNode next; - WaitNode(boolean interruptible, long nanos, long deadline) { + + Signaller(boolean interruptible, long nanos, long deadline) { this.thread = Thread.currentThread(); this.interruptControl = interruptible ? 1 : 0; this.nanos = nanos; this.deadline = deadline; } + final CompletableFuture tryFire(int ignore) { + Thread w; // no need to atomically claim + if ((w = thread) != null) { + thread = null; + LockSupport.unpark(w); + } + return null; + } public boolean isReleasable() { if (thread == null) return true; @@ -273,6 +1687,7 @@ public class CompletableFuture implements Future, CompletionStage { LockSupport.parkNanos(this, nanos); return isReleasable(); } + final boolean isLive() { return thread != null; } } /** @@ -280,1832 +1695,89 @@ public class CompletableFuture implements Future, CompletionStage { * interrupted. */ private Object waitingGet(boolean interruptible) { - WaitNode q = null; + Signaller q = null; boolean queued = false; - int spins = SPINS; - for (Object r;;) { - if ((r = result) != null) { - if (q != null) { // suppress unpark - q.thread = null; - if (q.interruptControl < 0) { - if (interruptible) { - removeWaiter(q); - return null; - } - Thread.currentThread().interrupt(); - } - } - postComplete(); // help release others - return r; - } + int spins = -1; + Object r; + while ((r = result) == null) { + if (spins < 0) + spins = (Runtime.getRuntime().availableProcessors() > 1) ? + 1 << 8 : 0; // Use brief spin-wait on multiprocessors else if (spins > 0) { - int rnd = ThreadLocalRandom.nextSecondarySeed(); - if (rnd == 0) - rnd = ThreadLocalRandom.current().nextInt(); - if (rnd >= 0) + if (ThreadLocalRandom.nextSecondarySeed() >= 0) --spins; } else if (q == null) - q = new WaitNode(interruptible, 0L, 0L); + q = new Signaller(interruptible, 0L, 0L); else if (!queued) - queued = UNSAFE.compareAndSwapObject(this, WAITERS, - q.next = waiters, q); + queued = tryPushStack(q); else if (interruptible && q.interruptControl < 0) { - removeWaiter(q); + q.thread = null; + cleanStack(); return null; } else if (q.thread != null && result == null) { try { ForkJoinPool.managedBlock(q); - } catch (InterruptedException ex) { + } catch (InterruptedException ie) { q.interruptControl = -1; } } } + if (q != null) { + q.thread = null; + if (q.interruptControl < 0) { + if (interruptible) + r = null; // report interruption + else + Thread.currentThread().interrupt(); + } + } + postComplete(); + return r; } /** - * Awaits completion or aborts on interrupt or timeout. - * - * @param nanos time to wait - * @return raw result + * Returns raw result after waiting, or null if interrupted, or + * throws TimeoutException on timeout. */ - private Object timedAwaitDone(long nanos) - throws InterruptedException, TimeoutException { - WaitNode q = null; + private Object timedGet(long nanos) throws TimeoutException { + if (Thread.interrupted()) + return null; + if (nanos <= 0L) + throw new TimeoutException(); + long d = System.nanoTime() + nanos; + Signaller q = new Signaller(true, nanos, d == 0L ? 1L : d); // avoid 0 boolean queued = false; - for (Object r;;) { - if ((r = result) != null) { - if (q != null) { - q.thread = null; - if (q.interruptControl < 0) { - removeWaiter(q); - throw new InterruptedException(); - } - } - postComplete(); - return r; - } - else if (q == null) { - if (nanos <= 0L) - throw new TimeoutException(); - long d = System.nanoTime() + nanos; - q = new WaitNode(true, nanos, d == 0L ? 1L : d); // avoid 0 - } - else if (!queued) - queued = UNSAFE.compareAndSwapObject(this, WAITERS, - q.next = waiters, q); - else if (q.interruptControl < 0) { - removeWaiter(q); - throw new InterruptedException(); - } - else if (q.nanos <= 0L) { - if (result == null) { - removeWaiter(q); - throw new TimeoutException(); - } + Object r; + // We intentionally don't spin here (as waitingGet does) because + // the call to nanoTime() above acts much like a spin. + while ((r = result) == null) { + if (!queued) + queued = tryPushStack(q); + else if (q.interruptControl < 0 || q.nanos <= 0L) { + q.thread = null; + cleanStack(); + if (q.interruptControl < 0) + return null; + throw new TimeoutException(); } else if (q.thread != null && result == null) { try { ForkJoinPool.managedBlock(q); - } catch (InterruptedException ex) { + } catch (InterruptedException ie) { q.interruptControl = -1; } } } + if (q.interruptControl < 0) + r = null; + q.thread = null; + postComplete(); + return r; } - /** - * Tries to unlink a timed-out or interrupted wait node to avoid - * accumulating garbage. Internal nodes are simply unspliced - * without CAS since it is harmless if they are traversed anyway - * by releasers. To avoid effects of unsplicing from already - * removed nodes, the list is retraversed in case of an apparent - * race. This is slow when there are a lot of nodes, but we don't - * expect lists to be long enough to outweigh higher-overhead - * schemes. - */ - private void removeWaiter(WaitNode node) { - if (node != null) { - node.thread = null; - retry: - for (;;) { // restart on removeWaiter race - for (WaitNode pred = null, q = waiters, s; q != null; q = s) { - s = q.next; - if (q.thread != null) - pred = q; - else if (pred != null) { - pred.next = s; - if (pred.thread == null) // check for race - continue retry; - } - else if (!UNSAFE.compareAndSwapObject(this, WAITERS, q, s)) - continue retry; - } - break; - } - } - } - - /* ------------- Async tasks -------------- */ - - /** - * A marker interface identifying asynchronous tasks produced by - * {@code async} methods. This may be useful for monitoring, - * debugging, and tracking asynchronous activities. - * - * @since 1.8 - */ - public static interface AsynchronousCompletionTask { - } - - /** Base class can act as either FJ or plain Runnable */ - @SuppressWarnings("serial") - abstract static class Async extends ForkJoinTask - implements Runnable, AsynchronousCompletionTask { - public final Void getRawResult() { return null; } - public final void setRawResult(Void v) { } - public final void run() { exec(); } - } - - /** - * Starts the given async task using the given executor, unless - * the executor is ForkJoinPool.commonPool and it has been - * disabled, in which case starts a new thread. - */ - static void execAsync(Executor e, Async r) { - if (e == ForkJoinPool.commonPool() && - ForkJoinPool.getCommonPoolParallelism() <= 1) - new Thread(r).start(); - else - e.execute(r); - } - - static final class AsyncRun extends Async { - final Runnable fn; - final CompletableFuture dst; - AsyncRun(Runnable fn, CompletableFuture dst) { - this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - fn.run(); - ex = null; - } catch (Throwable rex) { - ex = rex; - } - d.internalComplete(null, ex); - } - return true; - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AsyncSupply extends Async { - final Supplier fn; - final CompletableFuture dst; - AsyncSupply(Supplier fn, CompletableFuture dst) { - this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d; U u; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - u = fn.get(); - ex = null; - } catch (Throwable rex) { - ex = rex; - u = null; - } - d.internalComplete(u, ex); - } - return true; - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AsyncApply extends Async { - final T arg; - final Function fn; - final CompletableFuture dst; - AsyncApply(T arg, Function fn, - CompletableFuture dst) { - this.arg = arg; this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d; U u; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - u = fn.apply(arg); - ex = null; - } catch (Throwable rex) { - ex = rex; - u = null; - } - d.internalComplete(u, ex); - } - return true; - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AsyncCombine extends Async { - final T arg1; - final U arg2; - final BiFunction fn; - final CompletableFuture dst; - AsyncCombine(T arg1, U arg2, - BiFunction fn, - CompletableFuture dst) { - this.arg1 = arg1; this.arg2 = arg2; this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d; V v; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - v = fn.apply(arg1, arg2); - ex = null; - } catch (Throwable rex) { - ex = rex; - v = null; - } - d.internalComplete(v, ex); - } - return true; - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AsyncAccept extends Async { - final T arg; - final Consumer fn; - final CompletableFuture dst; - AsyncAccept(T arg, Consumer fn, - CompletableFuture dst) { - this.arg = arg; this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - fn.accept(arg); - ex = null; - } catch (Throwable rex) { - ex = rex; - } - d.internalComplete(null, ex); - } - return true; - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AsyncAcceptBoth extends Async { - final T arg1; - final U arg2; - final BiConsumer fn; - final CompletableFuture dst; - AsyncAcceptBoth(T arg1, U arg2, - BiConsumer fn, - CompletableFuture dst) { - this.arg1 = arg1; this.arg2 = arg2; this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - fn.accept(arg1, arg2); - ex = null; - } catch (Throwable rex) { - ex = rex; - } - d.internalComplete(null, ex); - } - return true; - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AsyncCompose extends Async { - final T arg; - final Function> fn; - final CompletableFuture dst; - AsyncCompose(T arg, - Function> fn, - CompletableFuture dst) { - this.arg = arg; this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d, fr; U u; Throwable ex; - if ((d = this.dst) != null && d.result == null) { - try { - CompletionStage cs = fn.apply(arg); - fr = (cs == null) ? null : cs.toCompletableFuture(); - ex = (fr == null) ? new NullPointerException() : null; - } catch (Throwable rex) { - ex = rex; - fr = null; - } - if (ex != null) - u = null; - else { - Object r = fr.result; - if (r == null) - r = fr.waitingGet(false); - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U ur = (U) r; - u = ur; - } - } - d.internalComplete(u, ex); - } - return true; - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AsyncWhenComplete extends Async { - final T arg1; - final Throwable arg2; - final BiConsumer fn; - final CompletableFuture dst; - AsyncWhenComplete(T arg1, Throwable arg2, - BiConsumer fn, - CompletableFuture dst) { - this.arg1 = arg1; this.arg2 = arg2; this.fn = fn; this.dst = dst; - } - public final boolean exec() { - CompletableFuture d; - if ((d = this.dst) != null && d.result == null) { - Throwable ex = arg2; - try { - fn.accept(arg1, ex); - } catch (Throwable rex) { - if (ex == null) - ex = rex; - } - d.internalComplete(arg1, ex); - } - return true; - } - private static final long serialVersionUID = 5232453952276885070L; - } - - /* ------------- Completions -------------- */ - - /** - * Simple linked list nodes to record completions, used in - * basically the same way as WaitNodes. (We separate nodes from - * the Completions themselves mainly because for the And and Or - * methods, the same Completion object resides in two lists.) - */ - static final class CompletionNode { - final Completion completion; - volatile CompletionNode next; - CompletionNode(Completion completion) { this.completion = completion; } - } - - // Opportunistically subclass AtomicInteger to use compareAndSet to claim. - @SuppressWarnings("serial") - abstract static class Completion extends AtomicInteger implements Runnable { - } - - static final class ThenApply extends Completion { - final CompletableFuture src; - final Function fn; - final CompletableFuture dst; - final Executor executor; - ThenApply(CompletableFuture src, - Function fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final Function fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Executor e = executor; - U u = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncApply(t, fn, dst)); - else - u = fn.apply(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(u, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenAccept extends Completion { - final CompletableFuture src; - final Consumer fn; - final CompletableFuture dst; - final Executor executor; - ThenAccept(CompletableFuture src, - Consumer fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final Consumer fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAccept(t, fn, dst)); - else - fn.accept(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenRun extends Completion { - final CompletableFuture src; - final Runnable fn; - final CompletableFuture dst; - final Executor executor; - ThenRun(CompletableFuture src, - Runnable fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final Runnable fn; - final CompletableFuture dst; - Object r; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(fn, dst)); - else - fn.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenCombine extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final BiFunction fn; - final CompletableFuture dst; - final Executor executor; - ThenCombine(CompletableFuture src, - CompletableFuture snd, - BiFunction fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final BiFunction fn; - final CompletableFuture dst; - Object r, s; T t; U u; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - (b = this.snd) != null && - (s = b.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex != null) - u = null; - else if (s instanceof AltResult) { - ex = ((AltResult)s).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - Executor e = executor; - V v = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncCombine(t, u, fn, dst)); - else - v = fn.apply(t, u); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(v, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenAcceptBoth extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final BiConsumer fn; - final CompletableFuture dst; - final Executor executor; - ThenAcceptBoth(CompletableFuture src, - CompletableFuture snd, - BiConsumer fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final BiConsumer fn; - final CompletableFuture dst; - Object r, s; T t; U u; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - (b = this.snd) != null && - (s = b.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex != null) - u = null; - else if (s instanceof AltResult) { - ex = ((AltResult)s).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAcceptBoth(t, u, fn, dst)); - else - fn.accept(t, u); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class RunAfterBoth extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final Runnable fn; - final CompletableFuture dst; - final Executor executor; - RunAfterBoth(CompletableFuture src, - CompletableFuture snd, - Runnable fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final Runnable fn; - final CompletableFuture dst; - Object r, s; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - (b = this.snd) != null && - (s = b.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null && (s instanceof AltResult)) - ex = ((AltResult)s).ex; - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(fn, dst)); - else - fn.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AndCompletion extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final CompletableFuture dst; - AndCompletion(CompletableFuture src, - CompletableFuture snd, - CompletableFuture dst) { - this.src = src; this.snd = snd; this.dst = dst; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final CompletableFuture dst; - Object r, s; Throwable ex; - if ((dst = this.dst) != null && - (a = this.src) != null && - (r = a.result) != null && - (b = this.snd) != null && - (s = b.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null && (s instanceof AltResult)) - ex = ((AltResult)s).ex; - dst.internalComplete(null, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ApplyToEither extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final Function fn; - final CompletableFuture dst; - final Executor executor; - ApplyToEither(CompletableFuture src, - CompletableFuture snd, - Function fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final Function fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (((a = this.src) != null && (r = a.result) != null) || - ((b = this.snd) != null && (r = b.result) != null)) && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Executor e = executor; - U u = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncApply(t, fn, dst)); - else - u = fn.apply(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(u, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class AcceptEither extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final Consumer fn; - final CompletableFuture dst; - final Executor executor; - AcceptEither(CompletableFuture src, - CompletableFuture snd, - Consumer fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final Consumer fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (((a = this.src) != null && (r = a.result) != null) || - ((b = this.snd) != null && (r = b.result) != null)) && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAccept(t, fn, dst)); - else - fn.accept(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class RunAfterEither extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final Runnable fn; - final CompletableFuture dst; - final Executor executor; - RunAfterEither(CompletableFuture src, - CompletableFuture snd, - Runnable fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.snd = snd; - this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final Runnable fn; - final CompletableFuture dst; - Object r; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (((a = this.src) != null && (r = a.result) != null) || - ((b = this.snd) != null && (r = b.result) != null)) && - compareAndSet(0, 1)) { - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - Executor e = executor; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(fn, dst)); - else - fn.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class OrCompletion extends Completion { - final CompletableFuture src; - final CompletableFuture snd; - final CompletableFuture dst; - OrCompletion(CompletableFuture src, - CompletableFuture snd, - CompletableFuture dst) { - this.src = src; this.snd = snd; this.dst = dst; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture b; - final CompletableFuture dst; - Object r, t; Throwable ex; - if ((dst = this.dst) != null && - (((a = this.src) != null && (r = a.result) != null) || - ((b = this.snd) != null && (r = b.result) != null)) && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - t = r; - } - dst.internalComplete(t, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ExceptionCompletion extends Completion { - final CompletableFuture src; - final Function fn; - final CompletableFuture dst; - ExceptionCompletion(CompletableFuture src, - Function fn, - CompletableFuture dst) { - this.src = src; this.fn = fn; this.dst = dst; - } - public final void run() { - final CompletableFuture a; - final Function fn; - final CompletableFuture dst; - Object r; T t = null; Throwable ex, dx = null; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if ((r instanceof AltResult) && - (ex = ((AltResult)r).ex) != null) { - try { - t = fn.apply(ex); - } catch (Throwable rex) { - dx = rex; - } - } - else { - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - dst.internalComplete(t, dx); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class WhenCompleteCompletion extends Completion { - final CompletableFuture src; - final BiConsumer fn; - final CompletableFuture dst; - final Executor executor; - WhenCompleteCompletion(CompletableFuture src, - BiConsumer fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final BiConsumer fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Executor e = executor; - Throwable dx = null; - try { - if (e != null) - execAsync(e, new AsyncWhenComplete(t, ex, fn, dst)); - else - fn.accept(t, ex); - } catch (Throwable rex) { - dx = rex; - } - if (e == null || dx != null) - dst.internalComplete(t, ex != null ? ex : dx); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenCopy extends Completion { - final CompletableFuture src; - final CompletableFuture dst; - ThenCopy(CompletableFuture src, - CompletableFuture dst) { - this.src = src; this.dst = dst; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - dst.internalComplete(t, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - // version of ThenCopy for CompletableFuture dst - static final class ThenPropagate extends Completion { - final CompletableFuture src; - final CompletableFuture dst; - ThenPropagate(CompletableFuture src, - CompletableFuture dst) { - this.src = src; this.dst = dst; - } - public final void run() { - final CompletableFuture a; - final CompletableFuture dst; - Object r; Throwable ex; - if ((dst = this.dst) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - dst.internalComplete(null, ex); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class HandleCompletion extends Completion { - final CompletableFuture src; - final BiFunction fn; - final CompletableFuture dst; - final Executor executor; - HandleCompletion(CompletableFuture src, - BiFunction fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final BiFunction fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Executor e = executor; - U u = null; - Throwable dx = null; - try { - if (e != null) - execAsync(e, new AsyncCombine(t, ex, fn, dst)); - else - u = fn.apply(t, ex); - } catch (Throwable rex) { - dx = rex; - } - if (e == null || dx != null) - dst.internalComplete(u, dx); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - static final class ThenCompose extends Completion { - final CompletableFuture src; - final Function> fn; - final CompletableFuture dst; - final Executor executor; - ThenCompose(CompletableFuture src, - Function> fn, - CompletableFuture dst, - Executor executor) { - this.src = src; this.fn = fn; this.dst = dst; - this.executor = executor; - } - public final void run() { - final CompletableFuture a; - final Function> fn; - final CompletableFuture dst; - Object r; T t; Throwable ex; Executor e; - if ((dst = this.dst) != null && - (fn = this.fn) != null && - (a = this.src) != null && - (r = a.result) != null && - compareAndSet(0, 1)) { - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - CompletableFuture c = null; - U u = null; - boolean complete = false; - if (ex == null) { - if ((e = executor) != null) - execAsync(e, new AsyncCompose(t, fn, dst)); - else { - try { - CompletionStage cs = fn.apply(t); - c = (cs == null) ? null : cs.toCompletableFuture(); - if (c == null) - ex = new NullPointerException(); - } catch (Throwable rex) { - ex = rex; - } - } - } - if (c != null) { - ThenCopy d = null; - Object s; - if ((s = c.result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenCopy(c, dst)); - while ((s = c.result) == null) { - if (UNSAFE.compareAndSwapObject - (c, COMPLETIONS, p.next = c.completions, p)) - break; - } - } - if (s != null && (d == null || d.compareAndSet(0, 1))) { - complete = true; - if (s instanceof AltResult) { - ex = ((AltResult)s).ex; // no rewrap - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - } - } - if (complete || ex != null) - dst.internalComplete(u, ex); - if (c != null) - c.helpPostComplete(); - } - } - private static final long serialVersionUID = 5232453952276885070L; - } - - // Implementations of stage methods with (plain, async, Executor) forms - - private CompletableFuture doThenApply - (Function fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ThenApply d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenApply(this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - U u = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncApply(t, fn, dst)); - else - u = fn.apply(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(u, ex); - } - helpPostComplete(); - return dst; - } - - private CompletableFuture doThenAccept(Consumer fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ThenAccept d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenAccept(this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAccept(t, fn, dst)); - else - fn.accept(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - return dst; - } - - private CompletableFuture doThenRun(Runnable action, - Executor e) { - if (action == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ThenRun d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = new CompletionNode - (d = new ThenRun(this, action, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(action, dst)); - else - action.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - return dst; - } - - private CompletableFuture doThenCombine - (CompletableFuture other, - BiFunction fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ThenCombine d = null; - Object r, s = null; - if ((r = result) == null || (s = other.result) == null) { - d = new ThenCombine(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r == null && (r = result) == null) || - (s == null && (s = other.result) == null)) { - if (q != null) { - if (s != null || - UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (r != null || - UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) { - if (s != null) - break; - q = new CompletionNode(d); - } - } - } - if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { - T t; U u; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex != null) - u = null; - else if (s instanceof AltResult) { - ex = ((AltResult)s).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - V v = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncCombine(t, u, fn, dst)); - else - v = fn.apply(t, u); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(v, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; - } - - private CompletableFuture doThenAcceptBoth - (CompletableFuture other, - BiConsumer fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ThenAcceptBoth d = null; - Object r, s = null; - if ((r = result) == null || (s = other.result) == null) { - d = new ThenAcceptBoth(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r == null && (r = result) == null) || - (s == null && (s = other.result) == null)) { - if (q != null) { - if (s != null || - UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (r != null || - UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) { - if (s != null) - break; - q = new CompletionNode(d); - } - } - } - if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { - T t; U u; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex != null) - u = null; - else if (s instanceof AltResult) { - ex = ((AltResult)s).ex; - u = null; - } - else { - @SuppressWarnings("unchecked") U us = (U) s; - u = us; - } - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAcceptBoth(t, u, fn, dst)); - else - fn.accept(t, u); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; - } - - private CompletableFuture doRunAfterBoth(CompletableFuture other, - Runnable action, - Executor e) { - if (other == null || action == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - RunAfterBoth d = null; - Object r, s = null; - if ((r = result) == null || (s = other.result) == null) { - d = new RunAfterBoth(this, other, action, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r == null && (r = result) == null) || - (s == null && (s = other.result) == null)) { - if (q != null) { - if (s != null || - UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (r != null || - UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) { - if (s != null) - break; - q = new CompletionNode(d); - } - } - } - if (r != null && s != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null && (s instanceof AltResult)) - ex = ((AltResult)s).ex; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(action, dst)); - else - action.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; - } - - private CompletableFuture doApplyToEither - (CompletableFuture other, - Function fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ApplyToEither d = null; - Object r; - if ((r = result) == null && (r = other.result) == null) { - d = new ApplyToEither(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r = result) == null && (r = other.result) == null) { - if (q != null) { - if (UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - q = new CompletionNode(d); - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - U u = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncApply(t, fn, dst)); - else - u = fn.apply(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(u, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; - } - - private CompletableFuture doAcceptEither - (CompletableFuture other, - Consumer fn, - Executor e) { - if (other == null || fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - AcceptEither d = null; - Object r; - if ((r = result) == null && (r = other.result) == null) { - d = new AcceptEither(this, other, fn, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r = result) == null && (r = other.result) == null) { - if (q != null) { - if (UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - q = new CompletionNode(d); - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncAccept(t, fn, dst)); - else - fn.accept(t); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; - } - - private CompletableFuture doRunAfterEither - (CompletableFuture other, - Runnable action, - Executor e) { - if (other == null || action == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - RunAfterEither d = null; - Object r; - if ((r = result) == null && (r = other.result) == null) { - d = new RunAfterEither(this, other, action, dst, e); - CompletionNode q = null, p = new CompletionNode(d); - while ((r = result) == null && (r = other.result) == null) { - if (q != null) { - if (UNSAFE.compareAndSwapObject - (other, COMPLETIONS, q.next = other.completions, q)) - break; - } - else if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - q = new CompletionNode(d); - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null) { - try { - if (e != null) - execAsync(e, new AsyncRun(action, dst)); - else - action.run(); - } catch (Throwable rex) { - ex = rex; - } - } - if (e == null || ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - other.helpPostComplete(); - return dst; - } - - private CompletableFuture doThenCompose - (Function> fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = null; - ThenCompose d = null; - Object r; - if ((r = result) == null) { - dst = new CompletableFuture(); - CompletionNode p = new CompletionNode - (d = new ThenCompose(this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject - (this, COMPLETIONS, p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - if (ex == null) { - if (e != null) { - if (dst == null) - dst = new CompletableFuture(); - execAsync(e, new AsyncCompose(t, fn, dst)); - } - else { - try { - CompletionStage cs = fn.apply(t); - if (cs == null || - (dst = cs.toCompletableFuture()) == null) - ex = new NullPointerException(); - } catch (Throwable rex) { - ex = rex; - } - } - } - if (dst == null) - dst = new CompletableFuture(); - if (ex != null) - dst.internalComplete(null, ex); - } - helpPostComplete(); - dst.helpPostComplete(); - return dst; - } - - private CompletableFuture doWhenComplete - (BiConsumer fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - WhenCompleteCompletion d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = - new CompletionNode(d = new WhenCompleteCompletion - (this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, - p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - Throwable dx = null; - try { - if (e != null) - execAsync(e, new AsyncWhenComplete(t, ex, fn, dst)); - else - fn.accept(t, ex); - } catch (Throwable rex) { - dx = rex; - } - if (e == null || dx != null) - dst.internalComplete(t, ex != null ? ex : dx); - } - helpPostComplete(); - return dst; - } - - private CompletableFuture doHandle - (BiFunction fn, - Executor e) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - HandleCompletion d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = - new CompletionNode(d = new HandleCompletion - (this, fn, dst, e)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, - p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t; Throwable ex; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - U u = null; - Throwable dx = null; - try { - if (e != null) - execAsync(e, new AsyncCombine(t, ex, fn, dst)); - else { - u = fn.apply(t, ex); - dx = null; - } - } catch (Throwable rex) { - dx = rex; - u = null; - } - if (e == null || dx != null) - dst.internalComplete(u, dx); - } - helpPostComplete(); - return dst; - } - - - // public methods + /* ------------- public methods -------------- */ /** * Creates a new incomplete CompletableFuture. @@ -2113,6 +1785,13 @@ public class CompletableFuture implements Future, CompletionStage { public CompletableFuture() { } + /** + * Creates a new complete CompletableFuture with given encoded result. + */ + private CompletableFuture(Object r) { + this.result = r; + } + /** * Returns a new CompletableFuture that is asynchronously completed * by a task running in the {@link ForkJoinPool#commonPool()} with @@ -2124,10 +1803,7 @@ public class CompletableFuture implements Future, CompletionStage { * @return the new CompletableFuture */ public static CompletableFuture supplyAsync(Supplier supplier) { - if (supplier == null) throw new NullPointerException(); - CompletableFuture f = new CompletableFuture(); - execAsync(ForkJoinPool.commonPool(), new AsyncSupply(supplier, f)); - return f; + return asyncSupplyStage(asyncPool, supplier); } /** @@ -2143,11 +1819,7 @@ public class CompletableFuture implements Future, CompletionStage { */ public static CompletableFuture supplyAsync(Supplier supplier, Executor executor) { - if (executor == null || supplier == null) - throw new NullPointerException(); - CompletableFuture f = new CompletableFuture(); - execAsync(executor, new AsyncSupply(supplier, f)); - return f; + return asyncSupplyStage(screenExecutor(executor), supplier); } /** @@ -2160,10 +1832,7 @@ public class CompletableFuture implements Future, CompletionStage { * @return the new CompletableFuture */ public static CompletableFuture runAsync(Runnable runnable) { - if (runnable == null) throw new NullPointerException(); - CompletableFuture f = new CompletableFuture(); - execAsync(ForkJoinPool.commonPool(), new AsyncRun(runnable, f)); - return f; + return asyncRunStage(asyncPool, runnable); } /** @@ -2178,11 +1847,7 @@ public class CompletableFuture implements Future, CompletionStage { */ public static CompletableFuture runAsync(Runnable runnable, Executor executor) { - if (executor == null || runnable == null) - throw new NullPointerException(); - CompletableFuture f = new CompletableFuture(); - execAsync(executor, new AsyncRun(runnable, f)); - return f; + return asyncRunStage(screenExecutor(executor), runnable); } /** @@ -2194,9 +1859,7 @@ public class CompletableFuture implements Future, CompletionStage { * @return the completed CompletableFuture */ public static CompletableFuture completedFuture(U value) { - CompletableFuture f = new CompletableFuture(); - f.result = (value == null) ? NIL : value; - return f; + return new CompletableFuture((value == null) ? NIL : value); } /** @@ -2220,21 +1883,8 @@ public class CompletableFuture implements Future, CompletionStage { * while waiting */ public T get() throws InterruptedException, ExecutionException { - Object r; Throwable ex, cause; - if ((r = result) == null && (r = waitingGet(true)) == null) - throw new InterruptedException(); - if (!(r instanceof AltResult)) { - @SuppressWarnings("unchecked") T tr = (T) r; - return tr; - } - if ((ex = ((AltResult)r).ex) == null) - return null; - if (ex instanceof CancellationException) - throw (CancellationException)ex; - if ((ex instanceof CompletionException) && - (cause = ex.getCause()) != null) - ex = cause; - throw new ExecutionException(ex); + Object r; + return reportGet((r = result) == null ? waitingGet(true) : r); } /** @@ -2252,24 +1902,9 @@ public class CompletableFuture implements Future, CompletionStage { */ public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { - Object r; Throwable ex, cause; + Object r; long nanos = unit.toNanos(timeout); - if (Thread.interrupted()) - throw new InterruptedException(); - if ((r = result) == null) - r = timedAwaitDone(nanos); - if (!(r instanceof AltResult)) { - @SuppressWarnings("unchecked") T tr = (T) r; - return tr; - } - if ((ex = ((AltResult)r).ex) == null) - return null; - if (ex instanceof CancellationException) - throw (CancellationException)ex; - if ((ex instanceof CompletionException) && - (cause = ex.getCause()) != null) - ex = cause; - throw new ExecutionException(ex); + return reportGet((r = result) == null ? timedGet(nanos) : r); } /** @@ -2287,20 +1922,8 @@ public class CompletableFuture implements Future, CompletionStage { * exceptionally or a completion computation threw an exception */ public T join() { - Object r; Throwable ex; - if ((r = result) == null) - r = waitingGet(false); - if (!(r instanceof AltResult)) { - @SuppressWarnings("unchecked") T tr = (T) r; - return tr; - } - if ((ex = ((AltResult)r).ex) == null) - return null; - if (ex instanceof CancellationException) - throw (CancellationException)ex; - if (ex instanceof CompletionException) - throw (CompletionException)ex; - throw new CompletionException(ex); + Object r; + return reportJoin((r = result) == null ? waitingGet(false) : r); } /** @@ -2314,20 +1937,8 @@ public class CompletableFuture implements Future, CompletionStage { * exceptionally or a completion computation threw an exception */ public T getNow(T valueIfAbsent) { - Object r; Throwable ex; - if ((r = result) == null) - return valueIfAbsent; - if (!(r instanceof AltResult)) { - @SuppressWarnings("unchecked") T tr = (T) r; - return tr; - } - if ((ex = ((AltResult)r).ex) == null) - return null; - if (ex instanceof CancellationException) - throw (CancellationException)ex; - if (ex instanceof CompletionException) - throw (CompletionException)ex; - throw new CompletionException(ex); + Object r; + return ((r = result) == null) ? valueIfAbsent : reportJoin(r); } /** @@ -2339,9 +1950,7 @@ public class CompletableFuture implements Future, CompletionStage { * to transition to a completed state, else {@code false} */ public boolean complete(T value) { - boolean triggered = result == null && - UNSAFE.compareAndSwapObject(this, RESULT, null, - value == null ? NIL : value); + boolean triggered = completeValue(value); postComplete(); return triggered; } @@ -2356,244 +1965,200 @@ public class CompletableFuture implements Future, CompletionStage { */ public boolean completeExceptionally(Throwable ex) { if (ex == null) throw new NullPointerException(); - boolean triggered = result == null && - UNSAFE.compareAndSwapObject(this, RESULT, null, new AltResult(ex)); + boolean triggered = internalComplete(new AltResult(ex)); postComplete(); return triggered; } - // CompletionStage methods - - public CompletableFuture thenApply - (Function fn) { - return doThenApply(fn, null); + public CompletableFuture thenApply( + Function fn) { + return uniApplyStage(null, fn); } - public CompletableFuture thenApplyAsync - (Function fn) { - return doThenApply(fn, ForkJoinPool.commonPool()); + public CompletableFuture thenApplyAsync( + Function fn) { + return uniApplyStage(asyncPool, fn); } - public CompletableFuture thenApplyAsync - (Function fn, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenApply(fn, executor); + public CompletableFuture thenApplyAsync( + Function fn, Executor executor) { + return uniApplyStage(screenExecutor(executor), fn); } - public CompletableFuture thenAccept - (Consumer action) { - return doThenAccept(action, null); + public CompletableFuture thenAccept(Consumer action) { + return uniAcceptStage(null, action); } - public CompletableFuture thenAcceptAsync - (Consumer action) { - return doThenAccept(action, ForkJoinPool.commonPool()); + public CompletableFuture thenAcceptAsync(Consumer action) { + return uniAcceptStage(asyncPool, action); } - public CompletableFuture thenAcceptAsync - (Consumer action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenAccept(action, executor); + public CompletableFuture thenAcceptAsync(Consumer action, + Executor executor) { + return uniAcceptStage(screenExecutor(executor), action); } - public CompletableFuture thenRun - (Runnable action) { - return doThenRun(action, null); + public CompletableFuture thenRun(Runnable action) { + return uniRunStage(null, action); } - public CompletableFuture thenRunAsync - (Runnable action) { - return doThenRun(action, ForkJoinPool.commonPool()); + public CompletableFuture thenRunAsync(Runnable action) { + return uniRunStage(asyncPool, action); } - public CompletableFuture thenRunAsync - (Runnable action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenRun(action, executor); + public CompletableFuture thenRunAsync(Runnable action, + Executor executor) { + return uniRunStage(screenExecutor(executor), action); } - public CompletableFuture thenCombine - (CompletionStage other, - BiFunction fn) { - return doThenCombine(other.toCompletableFuture(), fn, null); + public CompletableFuture thenCombine( + CompletionStage other, + BiFunction fn) { + return biApplyStage(null, other, fn); } - public CompletableFuture thenCombineAsync - (CompletionStage other, - BiFunction fn) { - return doThenCombine(other.toCompletableFuture(), fn, - ForkJoinPool.commonPool()); + public CompletableFuture thenCombineAsync( + CompletionStage other, + BiFunction fn) { + return biApplyStage(asyncPool, other, fn); } - public CompletableFuture thenCombineAsync - (CompletionStage other, - BiFunction fn, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenCombine(other.toCompletableFuture(), fn, executor); + public CompletableFuture thenCombineAsync( + CompletionStage other, + BiFunction fn, Executor executor) { + return biApplyStage(screenExecutor(executor), other, fn); } - public CompletableFuture thenAcceptBoth - (CompletionStage other, - BiConsumer action) { - return doThenAcceptBoth(other.toCompletableFuture(), action, null); + public CompletableFuture thenAcceptBoth( + CompletionStage other, + BiConsumer action) { + return biAcceptStage(null, other, action); } - public CompletableFuture thenAcceptBothAsync - (CompletionStage other, - BiConsumer action) { - return doThenAcceptBoth(other.toCompletableFuture(), action, - ForkJoinPool.commonPool()); + public CompletableFuture thenAcceptBothAsync( + CompletionStage other, + BiConsumer action) { + return biAcceptStage(asyncPool, other, action); } - public CompletableFuture thenAcceptBothAsync - (CompletionStage other, - BiConsumer action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenAcceptBoth(other.toCompletableFuture(), action, executor); + public CompletableFuture thenAcceptBothAsync( + CompletionStage other, + BiConsumer action, Executor executor) { + return biAcceptStage(screenExecutor(executor), other, action); } - public CompletableFuture runAfterBoth - (CompletionStage other, - Runnable action) { - return doRunAfterBoth(other.toCompletableFuture(), action, null); + public CompletableFuture runAfterBoth(CompletionStage other, + Runnable action) { + return biRunStage(null, other, action); } - public CompletableFuture runAfterBothAsync - (CompletionStage other, - Runnable action) { - return doRunAfterBoth(other.toCompletableFuture(), action, - ForkJoinPool.commonPool()); + public CompletableFuture runAfterBothAsync(CompletionStage other, + Runnable action) { + return biRunStage(asyncPool, other, action); } - public CompletableFuture runAfterBothAsync - (CompletionStage other, - Runnable action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doRunAfterBoth(other.toCompletableFuture(), action, executor); + public CompletableFuture runAfterBothAsync(CompletionStage other, + Runnable action, + Executor executor) { + return biRunStage(screenExecutor(executor), other, action); } - - public CompletableFuture applyToEither - (CompletionStage other, - Function fn) { - return doApplyToEither(other.toCompletableFuture(), fn, null); + public CompletableFuture applyToEither( + CompletionStage other, Function fn) { + return orApplyStage(null, other, fn); } - public CompletableFuture applyToEitherAsync - (CompletionStage other, - Function fn) { - return doApplyToEither(other.toCompletableFuture(), fn, - ForkJoinPool.commonPool()); + public CompletableFuture applyToEitherAsync( + CompletionStage other, Function fn) { + return orApplyStage(asyncPool, other, fn); } - public CompletableFuture applyToEitherAsync - (CompletionStage other, - Function fn, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doApplyToEither(other.toCompletableFuture(), fn, executor); + public CompletableFuture applyToEitherAsync( + CompletionStage other, Function fn, + Executor executor) { + return orApplyStage(screenExecutor(executor), other, fn); } - public CompletableFuture acceptEither - (CompletionStage other, - Consumer action) { - return doAcceptEither(other.toCompletableFuture(), action, null); + public CompletableFuture acceptEither( + CompletionStage other, Consumer action) { + return orAcceptStage(null, other, action); } - public CompletableFuture acceptEitherAsync - (CompletionStage other, - Consumer action) { - return doAcceptEither(other.toCompletableFuture(), action, - ForkJoinPool.commonPool()); + public CompletableFuture acceptEitherAsync( + CompletionStage other, Consumer action) { + return orAcceptStage(asyncPool, other, action); } - public CompletableFuture acceptEitherAsync - (CompletionStage other, - Consumer action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doAcceptEither(other.toCompletableFuture(), action, executor); + public CompletableFuture acceptEitherAsync( + CompletionStage other, Consumer action, + Executor executor) { + return orAcceptStage(screenExecutor(executor), other, action); } public CompletableFuture runAfterEither(CompletionStage other, Runnable action) { - return doRunAfterEither(other.toCompletableFuture(), action, null); + return orRunStage(null, other, action); } - public CompletableFuture runAfterEitherAsync - (CompletionStage other, - Runnable action) { - return doRunAfterEither(other.toCompletableFuture(), action, - ForkJoinPool.commonPool()); + public CompletableFuture runAfterEitherAsync(CompletionStage other, + Runnable action) { + return orRunStage(asyncPool, other, action); } - public CompletableFuture runAfterEitherAsync - (CompletionStage other, - Runnable action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doRunAfterEither(other.toCompletableFuture(), action, executor); + public CompletableFuture runAfterEitherAsync(CompletionStage other, + Runnable action, + Executor executor) { + return orRunStage(screenExecutor(executor), other, action); } - public CompletableFuture thenCompose - (Function> fn) { - return doThenCompose(fn, null); + public CompletableFuture thenCompose( + Function> fn) { + return uniComposeStage(null, fn); } - public CompletableFuture thenComposeAsync - (Function> fn) { - return doThenCompose(fn, ForkJoinPool.commonPool()); + public CompletableFuture thenComposeAsync( + Function> fn) { + return uniComposeStage(asyncPool, fn); } - public CompletableFuture thenComposeAsync - (Function> fn, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doThenCompose(fn, executor); + public CompletableFuture thenComposeAsync( + Function> fn, + Executor executor) { + return uniComposeStage(screenExecutor(executor), fn); } - public CompletableFuture whenComplete - (BiConsumer action) { - return doWhenComplete(action, null); + public CompletableFuture whenComplete( + BiConsumer action) { + return uniWhenCompleteStage(null, action); } - public CompletableFuture whenCompleteAsync - (BiConsumer action) { - return doWhenComplete(action, ForkJoinPool.commonPool()); + public CompletableFuture whenCompleteAsync( + BiConsumer action) { + return uniWhenCompleteStage(asyncPool, action); } - public CompletableFuture whenCompleteAsync - (BiConsumer action, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doWhenComplete(action, executor); + public CompletableFuture whenCompleteAsync( + BiConsumer action, Executor executor) { + return uniWhenCompleteStage(screenExecutor(executor), action); } - public CompletableFuture handle - (BiFunction fn) { - return doHandle(fn, null); + public CompletableFuture handle( + BiFunction fn) { + return uniHandleStage(null, fn); } - public CompletableFuture handleAsync - (BiFunction fn) { - return doHandle(fn, ForkJoinPool.commonPool()); + public CompletableFuture handleAsync( + BiFunction fn) { + return uniHandleStage(asyncPool, fn); } - public CompletableFuture handleAsync - (BiFunction fn, - Executor executor) { - if (executor == null) throw new NullPointerException(); - return doHandle(fn, executor); + public CompletableFuture handleAsync( + BiFunction fn, Executor executor) { + return uniHandleStage(screenExecutor(executor), fn); } /** - * Returns this CompletableFuture + * Returns this CompletableFuture. * * @return this CompletableFuture */ @@ -2618,52 +2183,13 @@ public class CompletableFuture implements Future, CompletionStage { * exceptionally * @return the new CompletableFuture */ - public CompletableFuture exceptionally - (Function fn) { - if (fn == null) throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - ExceptionCompletion d = null; - Object r; - if ((r = result) == null) { - CompletionNode p = - new CompletionNode(d = new ExceptionCompletion - (this, fn, dst)); - while ((r = result) == null) { - if (UNSAFE.compareAndSwapObject(this, COMPLETIONS, - p.next = completions, p)) - break; - } - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - T t = null; Throwable ex, dx = null; - if (r instanceof AltResult) { - if ((ex = ((AltResult)r).ex) != null) { - try { - t = fn.apply(ex); - } catch (Throwable rex) { - dx = rex; - } - } - } - else { - @SuppressWarnings("unchecked") T tr = (T) r; - t = tr; - } - dst.internalComplete(t, dx); - } - helpPostComplete(); - return dst; + public CompletableFuture exceptionally( + Function fn) { + return uniExceptionallyStage(fn); } /* ------------- Arbitrary-arity constructions -------------- */ - /* - * The basic plan of attack is to recursively form binary - * completion trees of elements. This can be overkill for small - * sets, but scales nicely. The And/All vs Or/Any forms use the - * same idea, but details differ. - */ - /** * Returns a new CompletableFuture that is completed when all of * the given CompletableFutures complete. If any of the given @@ -2688,82 +2214,7 @@ public class CompletableFuture implements Future, CompletionStage { * {@code null} */ public static CompletableFuture allOf(CompletableFuture... cfs) { - int len = cfs.length; // Directly handle empty and singleton cases - if (len > 1) - return allTree(cfs, 0, len - 1); - else { - CompletableFuture dst = new CompletableFuture(); - CompletableFuture f; - if (len == 0) - dst.result = NIL; - else if ((f = cfs[0]) == null) - throw new NullPointerException(); - else { - ThenPropagate d = null; - CompletionNode p = null; - Object r; - while ((r = f.result) == null) { - if (d == null) - d = new ThenPropagate(f, dst); - else if (p == null) - p = new CompletionNode(d); - else if (UNSAFE.compareAndSwapObject - (f, COMPLETIONS, p.next = f.completions, p)) - break; - } - if (r != null && (d == null || d.compareAndSet(0, 1))) - dst.internalComplete(null, (r instanceof AltResult) ? - ((AltResult)r).ex : null); - f.helpPostComplete(); - } - return dst; - } - } - - /** - * Recursively constructs an And'ed tree of CompletableFutures. - * Called only when array known to have at least two elements. - */ - private static CompletableFuture allTree(CompletableFuture[] cfs, - int lo, int hi) { - CompletableFuture fst, snd; - int mid = (lo + hi) >>> 1; - if ((fst = (lo == mid ? cfs[lo] : allTree(cfs, lo, mid))) == null || - (snd = (hi == mid+1 ? cfs[hi] : allTree(cfs, mid+1, hi))) == null) - throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - AndCompletion d = null; - CompletionNode p = null, q = null; - Object r = null, s = null; - while ((r = fst.result) == null || (s = snd.result) == null) { - if (d == null) - d = new AndCompletion(fst, snd, dst); - else if (p == null) - p = new CompletionNode(d); - else if (q == null) { - if (UNSAFE.compareAndSwapObject - (fst, COMPLETIONS, p.next = fst.completions, p)) - q = new CompletionNode(d); - } - else if (UNSAFE.compareAndSwapObject - (snd, COMPLETIONS, q.next = snd.completions, q)) - break; - } - if ((r != null || (r = fst.result) != null) && - (s != null || (s = snd.result) != null) && - (d == null || d.compareAndSet(0, 1))) { - Throwable ex; - if (r instanceof AltResult) - ex = ((AltResult)r).ex; - else - ex = null; - if (ex == null && (s instanceof AltResult)) - ex = ((AltResult)s).ex; - dst.internalComplete(null, ex); - } - fst.helpPostComplete(); - snd.helpPostComplete(); - return dst; + return andTree(cfs, 0, cfs.length - 1); } /** @@ -2782,92 +2233,7 @@ public class CompletableFuture implements Future, CompletionStage { * {@code null} */ public static CompletableFuture anyOf(CompletableFuture... cfs) { - int len = cfs.length; // Same idea as allOf - if (len > 1) - return anyTree(cfs, 0, len - 1); - else { - CompletableFuture dst = new CompletableFuture(); - CompletableFuture f; - if (len == 0) - ; // skip - else if ((f = cfs[0]) == null) - throw new NullPointerException(); - else { - ThenCopy d = null; - CompletionNode p = null; - Object r; - while ((r = f.result) == null) { - if (d == null) - d = new ThenCopy(f, dst); - else if (p == null) - p = new CompletionNode(d); - else if (UNSAFE.compareAndSwapObject - (f, COMPLETIONS, p.next = f.completions, p)) - break; - } - if (r != null && (d == null || d.compareAndSet(0, 1))) { - Throwable ex; Object t; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - t = r; - } - dst.internalComplete(t, ex); - } - f.helpPostComplete(); - } - return dst; - } - } - - /** - * Recursively constructs an Or'ed tree of CompletableFutures. - */ - private static CompletableFuture anyTree(CompletableFuture[] cfs, - int lo, int hi) { - CompletableFuture fst, snd; - int mid = (lo + hi) >>> 1; - if ((fst = (lo == mid ? cfs[lo] : anyTree(cfs, lo, mid))) == null || - (snd = (hi == mid+1 ? cfs[hi] : anyTree(cfs, mid+1, hi))) == null) - throw new NullPointerException(); - CompletableFuture dst = new CompletableFuture(); - OrCompletion d = null; - CompletionNode p = null, q = null; - Object r; - while ((r = fst.result) == null && (r = snd.result) == null) { - if (d == null) - d = new OrCompletion(fst, snd, dst); - else if (p == null) - p = new CompletionNode(d); - else if (q == null) { - if (UNSAFE.compareAndSwapObject - (fst, COMPLETIONS, p.next = fst.completions, p)) - q = new CompletionNode(d); - } - else if (UNSAFE.compareAndSwapObject - (snd, COMPLETIONS, q.next = snd.completions, q)) - break; - } - if ((r != null || (r = fst.result) != null || - (r = snd.result) != null) && - (d == null || d.compareAndSet(0, 1))) { - Throwable ex; Object t; - if (r instanceof AltResult) { - ex = ((AltResult)r).ex; - t = null; - } - else { - ex = null; - t = r; - } - dst.internalComplete(t, ex); - } - fst.helpPostComplete(); - snd.helpPostComplete(); - return dst; + return orTree(cfs, 0, cfs.length - 1); } /* ------------- Control and status methods -------------- */ @@ -2887,8 +2253,7 @@ public class CompletableFuture implements Future, CompletionStage { */ public boolean cancel(boolean mayInterruptIfRunning) { boolean cancelled = (result == null) && - UNSAFE.compareAndSwapObject - (this, RESULT, null, new AltResult(new CancellationException())); + internalComplete(new AltResult(new CancellationException())); postComplete(); return cancelled || isCancelled(); } @@ -2940,11 +2305,12 @@ public class CompletableFuture implements Future, CompletionStage { * Forcibly causes subsequent invocations of method {@link #get()} * and related methods to throw the given exception, whether or * not already completed. This method is designed for use only in - * recovery actions, and even in such situations may result in - * ongoing dependent completions using established versus + * error recovery actions, and even in such situations may result + * in ongoing dependent completions using established versus * overwritten outcomes. * * @param ex the exception + * @throws NullPointerException if the exception is null */ public void obtrudeException(Throwable ex) { if (ex == null) throw new NullPointerException(); @@ -2962,7 +2328,7 @@ public class CompletableFuture implements Future, CompletionStage { */ public int getNumberOfDependents() { int count = 0; - for (CompletionNode p = completions; p != null; p = p.next) + for (Completion p = stack; p != null; p = p.next) ++count; return count; } @@ -2993,20 +2359,19 @@ public class CompletableFuture implements Future, CompletionStage { // Unsafe mechanics private static final sun.misc.Unsafe UNSAFE; private static final long RESULT; - private static final long WAITERS; - private static final long COMPLETIONS; + private static final long STACK; + private static final long NEXT; static { try { - UNSAFE = sun.misc.Unsafe.getUnsafe(); + final sun.misc.Unsafe u; + UNSAFE = u = sun.misc.Unsafe.getUnsafe(); Class k = CompletableFuture.class; - RESULT = UNSAFE.objectFieldOffset - (k.getDeclaredField("result")); - WAITERS = UNSAFE.objectFieldOffset - (k.getDeclaredField("waiters")); - COMPLETIONS = UNSAFE.objectFieldOffset - (k.getDeclaredField("completions")); - } catch (Exception e) { - throw new Error(e); + RESULT = u.objectFieldOffset(k.getDeclaredField("result")); + STACK = u.objectFieldOffset(k.getDeclaredField("stack")); + NEXT = u.objectFieldOffset + (Completion.class.getDeclaredField("next")); + } catch (Exception x) { + throw new Error(x); } } } diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java b/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java index 6de60980cff..304ede5db50 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/CompletionStage.java @@ -407,7 +407,7 @@ public interface CompletionStage { /** * Returns a new CompletionStage that, when this and the other * given stage complete normally, executes the given action using - * the supplied executor + * the supplied executor. * * See the {@link CompletionStage} documentation for rules * covering exceptional completion. @@ -569,7 +569,7 @@ public interface CompletionStage { /** * Returns a new CompletionStage that, when either this or the * other given stage complete normally, executes the given action - * using supplied executor. + * using the supplied executor. * * See the {@link CompletionStage} documentation for rules * covering exceptional completion. @@ -649,10 +649,15 @@ public interface CompletionStage { (Function fn); /** - * Returns a new CompletionStage with the same result or exception - * as this stage, and when this stage completes, executes the - * given action with the result (or {@code null} if none) and the - * exception (or {@code null} if none) of this stage. + * Returns a new CompletionStage with the same result or exception as + * this stage, that executes the given action when this stage completes. + * + *

    When this stage is complete, the given action is invoked with the + * result (or {@code null} if none) and the exception (or {@code null} + * if none) of this stage as arguments. The returned stage is completed + * when the action returns. If the supplied action itself encounters an + * exception, then the returned stage exceptionally completes with this + * exception unless this stage also completed exceptionally. * * @param action the action to perform * @return the new CompletionStage @@ -661,12 +666,16 @@ public interface CompletionStage { (BiConsumer action); /** - * Returns a new CompletionStage with the same result or exception - * as this stage, and when this stage completes, executes the - * given action executes the given action using this stage's - * default asynchronous execution facility, with the result (or - * {@code null} if none) and the exception (or {@code null} if - * none) of this stage as arguments. + * Returns a new CompletionStage with the same result or exception as + * this stage, that executes the given action using this stage's + * default asynchronous execution facility when this stage completes. + * + *

    When this stage is complete, the given action is invoked with the + * result (or {@code null} if none) and the exception (or {@code null} + * if none) of this stage as arguments. The returned stage is completed + * when the action returns. If the supplied action itself encounters an + * exception, then the returned stage exceptionally completes with this + * exception unless this stage also completed exceptionally. * * @param action the action to perform * @return the new CompletionStage @@ -675,11 +684,16 @@ public interface CompletionStage { (BiConsumer action); /** - * Returns a new CompletionStage with the same result or exception - * as this stage, and when this stage completes, executes using - * the supplied Executor, the given action with the result (or - * {@code null} if none) and the exception (or {@code null} if - * none) of this stage as arguments. + * Returns a new CompletionStage with the same result or exception as + * this stage, that executes the given action using the supplied + * Executor when this stage completes. + * + *

    When this stage is complete, the given action is invoked with the + * result (or {@code null} if none) and the exception (or {@code null} + * if none) of this stage as arguments. The returned stage is completed + * when the action returns. If the supplied action itself encounters an + * exception, then the returned stage exceptionally completes with this + * exception unless this stage also completed exceptionally. * * @param action the action to perform * @param executor the executor to use for asynchronous execution @@ -693,9 +707,11 @@ public interface CompletionStage { * Returns a new CompletionStage that, when this stage completes * either normally or exceptionally, is executed with this stage's * result and exception as arguments to the supplied function. - * The given function is invoked with the result (or {@code null} - * if none) and the exception (or {@code null} if none) of this - * stage when complete as arguments. + * + *

    When this stage is complete, the given function is invoked + * with the result (or {@code null} if none) and the exception (or + * {@code null} if none) of this stage as arguments, and the + * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the * returned CompletionStage @@ -710,9 +726,11 @@ public interface CompletionStage { * either normally or exceptionally, is executed using this stage's * default asynchronous execution facility, with this stage's * result and exception as arguments to the supplied function. - * The given function is invoked with the result (or {@code null} - * if none) and the exception (or {@code null} if none) of this - * stage when complete as arguments. + * + *

    When this stage is complete, the given function is invoked + * with the result (or {@code null} if none) and the exception (or + * {@code null} if none) of this stage as arguments, and the + * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the * returned CompletionStage @@ -726,10 +744,12 @@ public interface CompletionStage { * Returns a new CompletionStage that, when this stage completes * either normally or exceptionally, is executed using the * supplied executor, with this stage's result and exception as - * arguments to the supplied function. The given function is - * invoked with the result (or {@code null} if none) and the - * exception (or {@code null} if none) of this stage when complete - * as arguments. + * arguments to the supplied function. + * + *

    When this stage is complete, the given function is invoked + * with the result (or {@code null} if none) and the exception (or + * {@code null} if none) of this stage as arguments, and the + * function's result is used to complete the returned stage. * * @param fn the function to use to compute the value of the * returned CompletionStage diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index 9f5e14914d0..c3ebf04d343 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -49,6 +49,7 @@ import java.util.concurrent.RejectedExecutionException; import java.util.concurrent.RunnableFuture; import java.util.concurrent.ThreadLocalRandom; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; import java.security.AccessControlContext; import java.security.ProtectionDomain; import java.security.Permissions; @@ -80,9 +81,9 @@ import java.security.Permissions; * *

    For applications that require separate or custom pools, a {@code * ForkJoinPool} may be constructed with a given target parallelism - * level; by default, equal to the number of available processors. The - * pool attempts to maintain enough active (or available) threads by - * dynamically adding, suspending, or resuming internal worker + * level; by default, equal to the number of available processors. + * The pool attempts to maintain enough active (or available) threads + * by dynamically adding, suspending, or resuming internal worker * threads, even if some tasks are stalled waiting to join others. * However, no such adjustments are guaranteed in the face of blocked * I/O or other unmanaged synchronization. The nested {@link @@ -142,6 +143,9 @@ import java.security.Permissions; * - the class name of a {@link ForkJoinWorkerThreadFactory} *

  • {@code java.util.concurrent.ForkJoinPool.common.exceptionHandler} * - the class name of a {@link UncaughtExceptionHandler} + *
  • {@code java.util.concurrent.ForkJoinPool.common.maximumSpares} + * - the maximum number of allowed extra threads to maintain target + * parallelism (default 256). * * If a {@link SecurityManager} is present and no factory is * specified, then the default pool uses a factory supplying @@ -178,7 +182,14 @@ public class ForkJoinPool extends AbstractExecutorService { * that may be stolen by other workers. Preference rules give * first priority to processing tasks from their own queues (LIFO * or FIFO, depending on mode), then to randomized FIFO steals of - * tasks in other queues. + * tasks in other queues. This framework began as vehicle for + * supporting tree-structured parallelism using work-stealing. + * Over time, its scalability advantages led to extensions and + * changes to better support more diverse usage contexts. Because + * most internal methods and nested classes are interrelated, + * their main rationale and descriptions are presented here; + * individual methods and nested classes contain only brief + * comments about details. * * WorkQueues * ========== @@ -198,201 +209,318 @@ public class ForkJoinPool extends AbstractExecutorService { * (http://research.sun.com/scalable/pubs/index.html) and * "Idempotent work stealing" by Michael, Saraswat, and Vechev, * PPoPP 2009 (http://portal.acm.org/citation.cfm?id=1504186). - * See also "Correct and Efficient Work-Stealing for Weak Memory - * Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013 - * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an - * analysis of memory ordering (atomic, volatile etc) issues. The - * main differences ultimately stem from GC requirements that we - * null out taken slots as soon as we can, to maintain as small a - * footprint as possible even in programs generating huge numbers - * of tasks. To accomplish this, we shift the CAS arbitrating pop - * vs poll (steal) from being on the indices ("base" and "top") to - * the slots themselves. So, both a successful pop and poll - * mainly entail a CAS of a slot from non-null to null. Because - * we rely on CASes of references, we do not need tag bits on base - * or top. They are simple ints as used in any circular + * The main differences ultimately stem from GC requirements that + * we null out taken slots as soon as we can, to maintain as small + * a footprint as possible even in programs generating huge + * numbers of tasks. To accomplish this, we shift the CAS + * arbitrating pop vs poll (steal) from being on the indices + * ("base" and "top") to the slots themselves. + * + * Adding tasks then takes the form of a classic array push(task): + * q.array[q.top] = task; ++q.top; + * + * (The actual code needs to null-check and size-check the array, + * properly fence the accesses, and possibly signal waiting + * workers to start scanning -- see below.) Both a successful pop + * and poll mainly entail a CAS of a slot from non-null to null. + * + * The pop operation (always performed by owner) is: + * if ((base != top) and + * (the task at top slot is not null) and + * (CAS slot to null)) + * decrement top and return task; + * + * And the poll operation (usually by a stealer) is + * if ((base != top) and + * (the task at base slot is not null) and + * (base has not changed) and + * (CAS slot to null)) + * increment base and return task; + * + * Because we rely on CASes of references, we do not need tag bits + * on base or top. They are simple ints as used in any circular * array-based queue (see for example ArrayDeque). Updates to the - * indices must still be ordered in a way that guarantees that top - * == base means the queue is empty, but otherwise may err on the - * side of possibly making the queue appear nonempty when a push, - * pop, or poll have not fully committed. Note that this means - * that the poll operation, considered individually, is not - * wait-free. One thief cannot successfully continue until another - * in-progress one (or, if previously empty, a push) completes. - * However, in the aggregate, we ensure at least probabilistic + * indices guarantee that top == base means the queue is empty, + * but otherwise may err on the side of possibly making the queue + * appear nonempty when a push, pop, or poll have not fully + * committed. (Method isEmpty() checks the case of a partially + * completed removal of the last element.) Because of this, the + * poll operation, considered individually, is not wait-free. One + * thief cannot successfully continue until another in-progress + * one (or, if previously empty, a push) completes. However, in + * the aggregate, we ensure at least probabilistic * non-blockingness. If an attempted steal fails, a thief always * chooses a different random victim target to try next. So, in * order for one thief to progress, it suffices for any * in-progress poll or new push on any empty queue to * complete. (This is why we normally use method pollAt and its * variants that try once at the apparent base index, else - * consider alternative actions, rather than method poll.) + * consider alternative actions, rather than method poll, which + * retries.) * - * This approach also enables support of a user mode in which local - * task processing is in FIFO, not LIFO order, simply by using - * poll rather than pop. This can be useful in message-passing - * frameworks in which tasks are never joined. However neither - * mode considers affinities, loads, cache localities, etc, so - * rarely provide the best possible performance on a given - * machine, but portably provide good throughput by averaging over - * these factors. (Further, even if we did try to use such - * information, we do not usually have a basis for exploiting it. - * For example, some sets of tasks profit from cache affinities, - * but others are harmed by cache pollution effects.) + * This approach also enables support of a user mode in which + * local task processing is in FIFO, not LIFO order, simply by + * using poll rather than pop. This can be useful in + * message-passing frameworks in which tasks are never joined. + * However neither mode considers affinities, loads, cache + * localities, etc, so rarely provide the best possible + * performance on a given machine, but portably provide good + * throughput by averaging over these factors. Further, even if + * we did try to use such information, we do not usually have a + * basis for exploiting it. For example, some sets of tasks + * profit from cache affinities, but others are harmed by cache + * pollution effects. Additionally, even though it requires + * scanning, long-term throughput is often best using random + * selection rather than directed selection policies, so cheap + * randomization of sufficient quality is used whenever + * applicable. Various Marsaglia XorShifts (some with different + * shift constants) are inlined at use points. * * WorkQueues are also used in a similar way for tasks submitted * to the pool. We cannot mix these tasks in the same queues used - * for work-stealing (this would contaminate lifo/fifo - * processing). Instead, we randomly associate submission queues + * by workers. Instead, we randomly associate submission queues * with submitting threads, using a form of hashing. The * ThreadLocalRandom probe value serves as a hash code for * choosing existing queues, and may be randomly repositioned upon * contention with other submitters. In essence, submitters act * like workers except that they are restricted to executing local * tasks that they submitted (or in the case of CountedCompleters, - * others with the same root task). However, because most - * shared/external queue operations are more expensive than - * internal, and because, at steady state, external submitters - * will compete for CPU with workers, ForkJoinTask.join and - * related methods disable them from repeatedly helping to process - * tasks if all workers are active. Insertion of tasks in shared + * others with the same root task). Insertion of tasks in shared * mode requires a lock (mainly to protect in the case of - * resizing) but we use only a simple spinlock (using bits in - * field qlock), because submitters encountering a busy queue move - * on to try or create other queues -- they block only when - * creating and registering new queues. + * resizing) but we use only a simple spinlock (using field + * qlock), because submitters encountering a busy queue move on to + * try or create other queues -- they block only when creating and + * registering new queues. Additionally, "qlock" saturates to an + * unlockable value (-1) at shutdown. Unlocking still can be and + * is performed by cheaper ordered writes of "qlock" in successful + * cases, but uses CAS in unsuccessful cases. * * Management * ========== * * The main throughput advantages of work-stealing stem from * decentralized control -- workers mostly take tasks from - * themselves or each other. We cannot negate this in the - * implementation of other management responsibilities. The main - * tactic for avoiding bottlenecks is packing nearly all - * essentially atomic control state into two volatile variables - * that are by far most often read (not written) as status and - * consistency checks. + * themselves or each other, at rates that can exceed a billion + * per second. The pool itself creates, activates (enables + * scanning for and running tasks), deactivates, blocks, and + * terminates threads, all with minimal central information. + * There are only a few properties that we can globally track or + * maintain, so we pack them into a small number of variables, + * often maintaining atomicity without blocking or locking. + * Nearly all essentially atomic control state is held in two + * volatile variables that are by far most often read (not + * written) as status and consistency checks. (Also, field + * "config" holds unchanging configuration state.) * - * Field "ctl" contains 64 bits holding all the information needed - * to atomically decide to add, inactivate, enqueue (on an event + * Field "ctl" contains 64 bits holding information needed to + * atomically decide to add, inactivate, enqueue (on an event * queue), dequeue, and/or re-activate workers. To enable this * packing, we restrict maximum parallelism to (1<<15)-1 (which is * far in excess of normal operating range) to allow ids, counts, * and their negations (used for thresholding) to fit into 16bit - * fields. + * subfields. * - * Field "plock" is a form of sequence lock with a saturating - * shutdown bit (similarly for per-queue "qlocks"), mainly - * protecting updates to the workQueues array, as well as to - * enable shutdown. When used as a lock, it is normally only very - * briefly held, so is nearly always available after at most a - * brief spin, but we use a monitor-based backup strategy to - * block when needed. + * Field "runState" holds lockable state bits (STARTED, STOP, etc) + * also protecting updates to the workQueues array. When used as + * a lock, it is normally held only for a few instructions (the + * only exceptions are one-time array initialization and uncommon + * resizing), so is nearly always available after at most a brief + * spin. But to be extra-cautious, after spinning, method + * awaitRunStateLock (called only if an initial CAS fails), uses a + * wait/notify mechanics on a builtin monitor to block when + * (rarely) needed. This would be a terrible idea for a highly + * contended lock, but most pools run without the lock ever + * contending after the spin limit, so this works fine as a more + * conservative alternative. Because we don't otherwise have an + * internal Object to use as a monitor, the "stealCounter" (an + * AtomicLong) is used when available (it too must be lazily + * initialized; see externalSubmit). + * + * Usages of "runState" vs "ctl" interact in only one case: + * deciding to add a worker thread (see tryAddWorker), in which + * case the ctl CAS is performed while the lock is held. * * Recording WorkQueues. WorkQueues are recorded in the - * "workQueues" array that is created upon first use and expanded - * if necessary. Updates to the array while recording new workers - * and unrecording terminated ones are protected from each other - * by a lock but the array is otherwise concurrently readable, and - * accessed directly. To simplify index-based operations, the - * array size is always a power of two, and all readers must - * tolerate null slots. Worker queues are at odd indices. Shared - * (submission) queues are at even indices, up to a maximum of 64 - * slots, to limit growth even if array needs to expand to add - * more workers. Grouping them together in this way simplifies and - * speeds up task scanning. + * "workQueues" array. The array is created upon first use (see + * externalSubmit) and expanded if necessary. Updates to the + * array while recording new workers and unrecording terminated + * ones are protected from each other by the runState lock, but + * the array is otherwise concurrently readable, and accessed + * directly. We also ensure that reads of the array reference + * itself never become too stale. To simplify index-based + * operations, the array size is always a power of two, and all + * readers must tolerate null slots. Worker queues are at odd + * indices. Shared (submission) queues are at even indices, up to + * a maximum of 64 slots, to limit growth even if array needs to + * expand to add more workers. Grouping them together in this way + * simplifies and speeds up task scanning. * * All worker thread creation is on-demand, triggered by task * submissions, replacement of terminated workers, and/or * compensation for blocked workers. However, all other support * code is set up to work with other policies. To ensure that we - * do not hold on to worker references that would prevent GC, ALL + * do not hold on to worker references that would prevent GC, All * accesses to workQueues are via indices into the workQueues * array (which is one source of some of the messy code * constructions here). In essence, the workQueues array serves as - * a weak reference mechanism. Thus for example the wait queue - * field of ctl stores indices, not references. Access to the - * workQueues in associated methods (for example signalWork) must - * both index-check and null-check the IDs. All such accesses - * ignore bad IDs by returning out early from what they are doing, - * since this can only be associated with termination, in which - * case it is OK to give up. All uses of the workQueues array - * also check that it is non-null (even if previously - * non-null). This allows nulling during termination, which is - * currently not necessary, but remains an option for - * resource-revocation-based shutdown schemes. It also helps - * reduce JIT issuance of uncommon-trap code, which tends to - * unnecessarily complicate control flow in some methods. + * a weak reference mechanism. Thus for example the stack top + * subfield of ctl stores indices, not references. * - * Event Queuing. Unlike HPC work-stealing frameworks, we cannot - * let workers spin indefinitely scanning for tasks when none can - * be found immediately, and we cannot start/resume workers unless - * there appear to be tasks available. On the other hand, we must - * quickly prod them into action when new tasks are submitted or - * generated. In many usages, ramp-up time to activate workers is - * the main limiting factor in overall performance (this is - * compounded at program start-up by JIT compilation and - * allocation). So we try to streamline this as much as possible. - * We park/unpark workers after placing in an event wait queue - * when they cannot find work. This "queue" is actually a simple - * Treiber stack, headed by the "id" field of ctl, plus a 15bit - * counter value (that reflects the number of times a worker has - * been inactivated) to avoid ABA effects (we need only as many - * version numbers as worker threads). Successors are held in - * field WorkQueue.nextWait. Queuing deals with several intrinsic - * races, mainly that a task-producing thread can miss seeing (and - * signalling) another thread that gave up looking for work but - * has not yet entered the wait queue. We solve this by requiring - * a full sweep of all workers (via repeated calls to method - * scan()) both before and after a newly waiting worker is added - * to the wait queue. Because enqueued workers may actually be - * rescanning rather than waiting, we set and clear the "parker" + * Queuing Idle Workers. Unlike HPC work-stealing frameworks, we + * cannot let workers spin indefinitely scanning for tasks when + * none can be found immediately, and we cannot start/resume + * workers unless there appear to be tasks available. On the + * other hand, we must quickly prod them into action when new + * tasks are submitted or generated. In many usages, ramp-up time + * to activate workers is the main limiting factor in overall + * performance, which is compounded at program start-up by JIT + * compilation and allocation. So we streamline this as much as + * possible. + * + * The "ctl" field atomically maintains active and total worker + * counts as well as a queue to place waiting threads so they can + * be located for signalling. Active counts also play the role of + * quiescence indicators, so are decremented when workers believe + * that there are no more tasks to execute. The "queue" is + * actually a form of Treiber stack. A stack is ideal for + * activating threads in most-recently used order. This improves + * performance and locality, outweighing the disadvantages of + * being prone to contention and inability to release a worker + * unless it is topmost on stack. We park/unpark workers after + * pushing on the idle worker stack (represented by the lower + * 32bit subfield of ctl) when they cannot find work. The top + * stack state holds the value of the "scanState" field of the + * worker: its index and status, plus a version counter that, in + * addition to the count subfields (also serving as version + * stamps) provide protection against Treiber stack ABA effects. + * + * Field scanState is used by both workers and the pool to manage + * and track whether a worker is INACTIVE (possibly blocked + * waiting for a signal), or SCANNING for tasks (when neither hold + * it is busy running tasks). When a worker is inactivated, its + * scanState field is set, and is prevented from executing tasks, + * even though it must scan once for them to avoid queuing + * races. Note that scanState updates lag queue CAS releases so + * usage requires care. When queued, the lower 16 bits of + * scanState must hold its pool index. So we place the index there + * upon initialization (see registerWorker) and otherwise keep it + * there or restore it when necessary. + * + * Memory ordering. See "Correct and Efficient Work-Stealing for + * Weak Memory Models" by Le, Pop, Cohen, and Nardelli, PPoPP 2013 + * (http://www.di.ens.fr/~zappa/readings/ppopp13.pdf) for an + * analysis of memory ordering requirements in work-stealing + * algorithms similar to the one used here. We usually need + * stronger than minimal ordering because we must sometimes signal + * workers, requiring Dekker-like full-fences to avoid lost + * signals. Arranging for enough ordering without expensive + * over-fencing requires tradeoffs among the supported means of + * expressing access constraints. The most central operations, + * taking from queues and updating ctl state, require full-fence + * CAS. Array slots are read using the emulation of volatiles + * provided by Unsafe. Access from other threads to WorkQueue + * base, top, and array requires a volatile load of the first of + * any of these read. We use the convention of declaring the + * "base" index volatile, and always read it before other fields. + * The owner thread must ensure ordered updates, so writes use + * ordered intrinsics unless they can piggyback on those for other + * writes. Similar conventions and rationales hold for other + * WorkQueue fields (such as "currentSteal") that are only written + * by owners but observed by others. + * + * Creating workers. To create a worker, we pre-increment total + * count (serving as a reservation), and attempt to construct a + * ForkJoinWorkerThread via its factory. Upon construction, the + * new thread invokes registerWorker, where it constructs a + * WorkQueue and is assigned an index in the workQueues array + * (expanding the array if necessary). The thread is then + * started. Upon any exception across these steps, or null return + * from factory, deregisterWorker adjusts counts and records + * accordingly. If a null return, the pool continues running with + * fewer than the target number workers. If exceptional, the + * exception is propagated, generally to some external caller. + * Worker index assignment avoids the bias in scanning that would + * occur if entries were sequentially packed starting at the front + * of the workQueues array. We treat the array as a simple + * power-of-two hash table, expanding as needed. The seedIndex + * increment ensures no collisions until a resize is needed or a + * worker is deregistered and replaced, and thereafter keeps + * probability of collision low. We cannot use + * ThreadLocalRandom.getProbe() for similar purposes here because + * the thread has not started yet, but do so for creating + * submission queues for existing external threads. + * + * Deactivation and waiting. Queuing encounters several intrinsic + * races; most notably that a task-producing thread can miss + * seeing (and signalling) another thread that gave up looking for + * work but has not yet entered the wait queue. When a worker + * cannot find a task to steal, it deactivates and enqueues. Very + * often, the lack of tasks is transient due to GC or OS + * scheduling. To reduce false-alarm deactivation, scanners + * compute checksums of queue states during sweeps. (The + * stability checks used here and elsewhere are probabilistic + * variants of snapshot techniques -- see Herlihy & Shavit.) + * Workers give up and try to deactivate only after the sum is + * stable across scans. Further, to avoid missed signals, they + * repeat this scanning process after successful enqueuing until + * again stable. In this state, the worker cannot take/run a task + * it sees until it is released from the queue, so the worker + * itself eventually tries to release itself or any successor (see + * tryRelease). Otherwise, upon an empty scan, a deactivated + * worker uses an adaptive local spin construction (see awaitWork) + * before blocking (via park). Note the unusual conventions about + * Thread.interrupts surrounding parking and other blocking: + * Because interrupts are used solely to alert threads to check + * termination, which is checked anyway upon blocking, we clear + * status (using Thread.interrupted) before any call to park, so + * that park does not immediately return due to status being set + * via some other unrelated call to interrupt in user code. + * + * Signalling and activation. Workers are created or activated + * only when there appears to be at least one task they might be + * able to find and execute. Upon push (either by a worker or an + * external submission) to a previously (possibly) empty queue, + * workers are signalled if idle, or created if fewer exist than + * the given parallelism level. These primary signals are + * buttressed by others whenever other threads remove a task from + * a queue and notice that there are other tasks there as well. + * On most platforms, signalling (unpark) overhead time is + * noticeably long, and the time between signalling a thread and + * it actually making progress can be very noticeably long, so it + * is worth offloading these delays from critical paths as much as + * possible. Also, because inactive workers are often rescanning + * or spinning rather than blocking, we set and clear the "parker" * field of WorkQueues to reduce unnecessary calls to unpark. * (This requires a secondary recheck to avoid missed signals.) - * Note the unusual conventions about Thread.interrupts - * surrounding parking and other blocking: Because interrupts are - * used solely to alert threads to check termination, which is - * checked anyway upon blocking, we clear status (using - * Thread.interrupted) before any call to park, so that park does - * not immediately return due to status being set via some other - * unrelated call to interrupt in user code. - * - * Signalling. We create or wake up workers only when there - * appears to be at least one task they might be able to find and - * execute. When a submission is added or another worker adds a - * task to a queue that has fewer than two tasks, they signal - * waiting workers (or trigger creation of new ones if fewer than - * the given parallelism level -- signalWork). These primary - * signals are buttressed by others whenever other threads remove - * a task from a queue and notice that there are other tasks there - * as well. So in general, pools will be over-signalled. On most - * platforms, signalling (unpark) overhead time is noticeably - * long, and the time between signalling a thread and it actually - * making progress can be very noticeably long, so it is worth - * offloading these delays from critical paths as much as - * possible. Additionally, workers spin-down gradually, by staying - * alive so long as they see the ctl state changing. Similar - * stability-sensing techniques are also used before blocking in - * awaitJoin and helpComplete. * * Trimming workers. To release resources after periods of lack of * use, a worker starting to wait when the pool is quiescent will - * time out and terminate if the pool has remained quiescent for a - * given period -- a short period if there are more threads than - * parallelism, longer as the number of threads decreases. This - * will slowly propagate, eventually terminating all workers after - * periods of non-use. + * time out and terminate (see awaitWork) if the pool has remained + * quiescent for period IDLE_TIMEOUT, increasing the period as the + * number of threads decreases, eventually removing all workers. + * Also, when more than two spare threads exist, excess threads + * are immediately terminated at the next quiescent point. + * (Padding by two avoids hysteresis.) + * + * Shutdown and Termination. A call to shutdownNow invokes + * tryTerminate to atomically set a runState bit. The calling + * thread, as well as every other worker thereafter terminating, + * helps terminate others by setting their (qlock) status, + * cancelling their unprocessed tasks, and waking them up, doing + * so repeatedly until stable (but with a loop bounded by the + * number of workers). Calls to non-abrupt shutdown() preface + * this by checking whether termination should commence. This + * relies primarily on the active count bits of "ctl" maintaining + * consensus -- tryTerminate is called from awaitWork whenever + * quiescent. However, external submitters do not take part in + * this consensus. So, tryTerminate sweeps through queues (until + * stable) to ensure lack of in-flight submissions and workers + * about to process them before triggering the "STOP" phase of + * termination. (Note: there is an intrinsic conflict if + * helpQuiescePool is called when shutdown is enabled. Both wait + * for quiescence, but tryTerminate is biased to not trigger until + * helpQuiescePool completes.) * - * Shutdown and Termination. A call to shutdownNow atomically sets - * a plock bit and then (non-atomically) sets each worker's - * qlock status, cancels all unprocessed tasks, and wakes up - * all waiting workers. Detecting whether termination should - * commence after a non-abrupt shutdown() call requires more work - * and bookkeeping. We need consensus about quiescence (i.e., that - * there is no more work). The active count provides a primary - * indication but non-abrupt shutdown still requires a rechecking - * scan for any workers that are inactive but not queued. * * Joining Tasks * ============= @@ -403,9 +531,9 @@ public class ForkJoinPool extends AbstractExecutorService { * just let them block (as in Thread.join). We also cannot just * reassign the joiner's run-time stack with another and replace * it later, which would be a form of "continuation", that even if - * possible is not necessarily a good idea since we sometimes need - * both an unblocked task and its continuation to progress. - * Instead we combine two tactics: + * possible is not necessarily a good idea since we may need both + * an unblocked task and its continuation to progress. Instead we + * combine two tactics: * * Helping: Arranging for the joiner to execute some task that it * would be running if the steal had not occurred. @@ -425,16 +553,16 @@ public class ForkJoinPool extends AbstractExecutorService { * The ManagedBlocker extension API can't use helping so relies * only on compensation in method awaitBlocker. * - * The algorithm in tryHelpStealer entails a form of "linear" - * helping: Each worker records (in field currentSteal) the most - * recent task it stole from some other worker. Plus, it records - * (in field currentJoin) the task it is currently actively - * joining. Method tryHelpStealer uses these markers to try to - * find a worker to help (i.e., steal back a task from and execute - * it) that could hasten completion of the actively joined task. - * In essence, the joiner executes a task that would be on its own - * local deque had the to-be-joined task not been stolen. This may - * be seen as a conservative variant of the approach in Wagner & + * The algorithm in helpStealer entails a form of "linear + * helping". Each worker records (in field currentSteal) the most + * recent task it stole from some other worker (or a submission). + * It also records (in field currentJoin) the task it is currently + * actively joining. Method helpStealer uses these markers to try + * to find a worker to help (i.e., steal back a task from and + * execute it) that could hasten completion of the actively joined + * task. Thus, the joiner executes a task that would be on its + * own local deque had the to-be-joined task not been stolen. This + * is a conservative variant of the approach described in Wagner & * Calder "Leapfrogging: a portable technique for implementing * efficient futures" SIGPLAN Notices, 1993 * (http://portal.acm.org/citation.cfm?id=155354). It differs in @@ -452,37 +580,40 @@ public class ForkJoinPool extends AbstractExecutorService { * which means that we miss links in the chain during long-lived * tasks, GC stalls etc (which is OK since blocking in such cases * is usually a good idea). (4) We bound the number of attempts - * to find work (see MAX_HELP) and fall back to suspending the + * to find work using checksums and fall back to suspending the * worker and if necessary replacing it with another. * - * Helping actions for CountedCompleters are much simpler: Method - * helpComplete can take and execute any task with the same root - * as the task being waited on. However, this still entails some - * traversal of completer chains, so is less efficient than using - * CountedCompleters without explicit joins. + * Helping actions for CountedCompleters do not require tracking + * currentJoins: Method helpComplete takes and executes any task + * with the same root as the task being waited on (preferring + * local pops to non-local polls). However, this still entails + * some traversal of completer chains, so is less efficient than + * using CountedCompleters without explicit joins. * - * It is impossible to keep exactly the target parallelism number - * of threads running at any given time. Determining the - * existence of conservatively safe helping targets, the - * availability of already-created spares, and the apparent need - * to create new spares are all racy, so we rely on multiple - * retries of each. Compensation in the apparent absence of - * helping opportunities is challenging to control on JVMs, where - * GC and other activities can stall progress of tasks that in - * turn stall out many other dependent tasks, without us being - * able to determine whether they will ever require compensation. - * Even though work-stealing otherwise encounters little - * degradation in the presence of more threads than cores, - * aggressively adding new threads in such cases entails risk of - * unwanted positive feedback control loops in which more threads - * cause more dependent stalls (as well as delayed progress of - * unblocked threads to the point that we know they are available) - * leading to more situations requiring more threads, and so - * on. This aspect of control can be seen as an (analytically - * intractable) game with an opponent that may choose the worst - * (for us) active thread to stall at any time. We take several - * precautions to bound losses (and thus bound gains), mainly in - * methods tryCompensate and awaitJoin. + * Compensation does not aim to keep exactly the target + * parallelism number of unblocked threads running at any given + * time. Some previous versions of this class employed immediate + * compensations for any blocked join. However, in practice, the + * vast majority of blockages are transient byproducts of GC and + * other JVM or OS activities that are made worse by replacement. + * Currently, compensation is attempted only after validating that + * all purportedly active threads are processing tasks by checking + * field WorkQueue.scanState, which eliminates most false + * positives. Also, compensation is bypassed (tolerating fewer + * threads) in the most common case in which it is rarely + * beneficial: when a worker with an empty queue (thus no + * continuation tasks) blocks on a join and there still remain + * enough threads to ensure liveness. + * + * The compensation mechanism may be bounded. Bounds for the + * commonPool (see commonMaxSpares) better enable JVMs to cope + * with programming errors and abuse before running out of + * resources to do so. In other cases, users may supply factories + * that limit thread construction. The effects of bounding in this + * pool (like all others) is imprecise. Total worker counts are + * decremented when threads deregister, not when they exit and + * resources are reclaimed by the JVM and OS. So the number of + * simultaneously live threads may transiently exceed bounds. * * Common Pool * =========== @@ -492,34 +623,52 @@ public class ForkJoinPool extends AbstractExecutorService { * never be used, we minimize initial construction overhead and * footprint to the setup of about a dozen fields, with no nested * allocation. Most bootstrapping occurs within method - * fullExternalPush during the first submission to the pool. + * externalSubmit during the first submission to the pool. * * When external threads submit to the common pool, they can - * perform subtask processing (see externalHelpJoin and related - * methods). This caller-helps policy makes it sensible to set - * common pool parallelism level to one (or more) less than the - * total number of available cores, or even zero for pure - * caller-runs. We do not need to record whether external - * submissions are to the common pool -- if not, externalHelpJoin - * returns quickly (at the most helping to signal some common pool - * workers). These submitters would otherwise be blocked waiting - * for completion, so the extra effort (with liberally sprinkled - * task status checks) in inapplicable cases amounts to an odd - * form of limited spin-wait before blocking in ForkJoinTask.join. + * perform subtask processing (see externalHelpComplete and + * related methods) upon joins. This caller-helps policy makes it + * sensible to set common pool parallelism level to one (or more) + * less than the total number of available cores, or even zero for + * pure caller-runs. We do not need to record whether external + * submissions are to the common pool -- if not, external help + * methods return quickly. These submitters would otherwise be + * blocked waiting for completion, so the extra effort (with + * liberally sprinkled task status checks) in inapplicable cases + * amounts to an odd form of limited spin-wait before blocking in + * ForkJoinTask.join. * * As a more appropriate default in managed environments, unless * overridden by system properties, we use workers of subclass * InnocuousForkJoinWorkerThread when there is a SecurityManager * present. These workers have no permissions set, do not belong * to any user-defined ThreadGroup, and erase all ThreadLocals - * after executing any top-level task (see WorkQueue.runTask). The - * associated mechanics (mainly in ForkJoinWorkerThread) may be - * JVM-dependent and must access particular Thread class fields to - * achieve this effect. + * after executing any top-level task (see WorkQueue.runTask). + * The associated mechanics (mainly in ForkJoinWorkerThread) may + * be JVM-dependent and must access particular Thread class fields + * to achieve this effect. * * Style notes * =========== * + * Memory ordering relies mainly on Unsafe intrinsics that carry + * the further responsibility of explicitly performing null- and + * bounds- checks otherwise carried out implicitly by JVMs. This + * can be awkward and ugly, but also reflects the need to control + * outcomes across the unusual cases that arise in very racy code + * with very few invariants. So these explicit checks would exist + * in some form anyway. All fields are read into locals before + * use, and null-checked if they are references. This is usually + * done in a "C"-like style of listing declarations at the heads + * of methods or blocks, and using inline assignments on first + * encounter. Array bounds-checks are usually performed by + * masking with array.length-1, which relies on the invariant that + * these arrays are created with positive lengths, which is itself + * paranoically checked. Nearly all explicit checks lead to + * bypass/return, not exception throws, because they may + * legitimately arise due to cancellation/revocation during + * shutdown. + * * There is a lot of representation-level coupling among classes * ForkJoinPool, ForkJoinWorkerThread, and ForkJoinTask. The * fields of WorkQueue maintain data structures managed by @@ -527,22 +676,13 @@ public class ForkJoinPool extends AbstractExecutorService { * trying to reduce this, since any associated future changes in * representations will need to be accompanied by algorithmic * changes anyway. Several methods intrinsically sprawl because - * they must accumulate sets of consistent reads of volatiles held - * in local variables. Methods signalWork() and scan() are the - * main bottlenecks, so are especially heavily - * micro-optimized/mangled. There are lots of inline assignments - * (of form "while ((local = field) != 0)") which are usually the - * simplest way to ensure the required read orderings (which are - * sometimes critical). This leads to a "C"-like style of listing - * declarations of these locals at the heads of methods or blocks. - * There are several occurrences of the unusual "do {} while - * (!cas...)" which is the simplest way to force an update of a - * CAS'ed variable. There are also other coding oddities (including - * several unnecessary-looking hoisted null checks) that help - * some methods perform reasonably even when interpreted (not - * compiled). + * they must accumulate sets of consistent reads of fields held in + * local variables. There are also other coding oddities + * (including several unnecessary-looking hoisted null checks) + * that help some methods perform reasonably even when interpreted + * (not compiled). * - * The order of declarations in this file is: + * The order of declarations in this file is (with a few exceptions): * (1) Static utility functions * (2) Nested (static) classes * (3) Static fields @@ -609,56 +749,37 @@ public class ForkJoinPool extends AbstractExecutorService { public final boolean exec() { return true; } } + // Constants shared across ForkJoinPool and WorkQueue + + // Bounds + static final int SMASK = 0xffff; // short bits == max index + static final int MAX_CAP = 0x7fff; // max #workers - 1 + static final int EVENMASK = 0xfffe; // even short bits + static final int SQMASK = 0x007e; // max 64 (even) slots + + // Masks and units for WorkQueue.scanState and ctl sp subfield + static final int SCANNING = 1; // false when running tasks + static final int INACTIVE = 1 << 31; // must be negative + static final int SS_SEQ = 1 << 16; // version count + + // Mode bits for ForkJoinPool.config and WorkQueue.config + static final int MODE_MASK = 0xffff << 16; // top half of int + static final int LIFO_QUEUE = 0; + static final int FIFO_QUEUE = 1 << 16; + static final int SHARED_QUEUE = 1 << 31; // must be negative + /** * Queues supporting work-stealing as well as external task - * submission. See above for main rationale and algorithms. - * Implementation relies heavily on "Unsafe" intrinsics - * and selective use of "volatile": - * - * Field "base" is the index (mod array.length) of the least valid - * queue slot, which is always the next position to steal (poll) - * from if nonempty. Reads and writes require volatile orderings - * but not CAS, because updates are only performed after slot - * CASes. - * - * Field "top" is the index (mod array.length) of the next queue - * slot to push to or pop from. It is written only by owner thread - * for push, or under lock for external/shared push, and accessed - * by other threads only after reading (volatile) base. Both top - * and base are allowed to wrap around on overflow, but (top - - * base) (or more commonly -(base - top) to force volatile read of - * base before top) still estimates size. The lock ("qlock") is - * forced to -1 on termination, causing all further lock attempts - * to fail. (Note: we don't need CAS for termination state because - * upon pool shutdown, all shared-queues will stop being used - * anyway.) Nearly all lock bodies are set up so that exceptions - * within lock bodies are "impossible" (modulo JVM errors that - * would cause failure anyway.) - * - * The array slots are read and written using the emulation of - * volatiles/atomics provided by Unsafe. Insertions must in - * general use putOrderedObject as a form of releasing store to - * ensure that all writes to the task object are ordered before - * its publication in the queue. All removals entail a CAS to - * null. The array is always a power of two. To ensure safety of - * Unsafe array operations, all accesses perform explicit null - * checks and implicit bounds checks via power-of-two masking. - * - * In addition to basic queuing support, this class contains - * fields described elsewhere to control execution. It turns out - * to work better memory-layout-wise to include them in this class - * rather than a separate class. - * + * submission. See above for descriptions and algorithms. * Performance on most platforms is very sensitive to placement of * instances of both WorkQueues and their arrays -- we absolutely * do not want multiple WorkQueue instances or multiple queue - * arrays sharing cache lines. (It would be best for queue objects - * and their arrays to share, but there is nothing available to - * help arrange that). The @Contended annotation alerts JVMs to - * try to keep instances apart. + * arrays sharing cache lines. The @Contended annotation alerts + * JVMs to try to keep instances apart. */ @sun.misc.Contended static final class WorkQueue { + /** * Capacity of work-stealing queue array upon initialization. * Must be a power of two; at least 4, but should be larger to @@ -679,13 +800,13 @@ public class ForkJoinPool extends AbstractExecutorService { */ static final int MAXIMUM_QUEUE_CAPACITY = 1 << 26; // 64M - volatile int eventCount; // encoded inactivation count; < 0 if inactive - int nextWait; // encoded record of next event waiter + // Instance fields + volatile int scanState; // versioned, <0: inactive; odd:scanning + int stackPred; // pool stack (ctl) predecessor int nsteals; // number of steals - int hint; // steal index hint - short poolIndex; // index of this queue in pool - final short mode; // 0: lifo, > 0: fifo, < 0: shared - volatile int qlock; // 1: locked, -1: terminate; else 0 + int hint; // randomization and stealer index hint + int config; // pool index and mode + volatile int qlock; // 1: locked, < 0: terminate; else 0 volatile int base; // index of next slot for poll int top; // index of next slot for push ForkJoinTask[] array; // the elements (initially unallocated) @@ -693,18 +814,22 @@ public class ForkJoinPool extends AbstractExecutorService { final ForkJoinWorkerThread owner; // owning thread or null if shared volatile Thread parker; // == owner during call to park; else null volatile ForkJoinTask currentJoin; // task being joined in awaitJoin - ForkJoinTask currentSteal; // current non-local task being executed + volatile ForkJoinTask currentSteal; // mainly used by helpStealer - WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner, int mode, - int seed) { + WorkQueue(ForkJoinPool pool, ForkJoinWorkerThread owner) { this.pool = pool; this.owner = owner; - this.mode = (short)mode; - this.hint = seed; // store initial seed for runWorker // Place indices in the center of array (that is not yet allocated) base = top = INITIAL_QUEUE_CAPACITY >>> 1; } + /** + * Returns an exportable index (used by ForkJoinWorkerThread). + */ + final int getPoolIndex() { + return (config & 0xffff) >>> 1; // ignore odd/even tag bit + } + /** * Returns the approximate number of tasks in the queue. */ @@ -719,12 +844,10 @@ public class ForkJoinPool extends AbstractExecutorService { * near-empty queue has at least one unclaimed task. */ final boolean isEmpty() { - ForkJoinTask[] a; int m, s; - int n = base - (s = top); - return (n >= 0 || - (n == -1 && - ((a = array) == null || - (m = a.length - 1) < 0 || + ForkJoinTask[] a; int n, m, s; + return ((n = base - (s = top)) >= 0 || + (n == -1 && // possibly one task + ((a = array) == null || (m = a.length - 1) < 0 || U.getObject (a, (long)((m & (s - 1)) << ASHIFT) + ABASE) == null))); } @@ -738,12 +861,15 @@ public class ForkJoinPool extends AbstractExecutorService { */ final void push(ForkJoinTask task) { ForkJoinTask[] a; ForkJoinPool p; - int s = top, n; + int b = base, s = top, n; if ((a = array) != null) { // ignore if queue removed - int m = a.length - 1; + int m = a.length - 1; // fenced write for task visibility U.putOrderedObject(a, ((m & s) << ASHIFT) + ABASE, task); - if ((n = (top = s + 1) - base) <= 2) - (p = pool).signalWork(p.workQueues, this); + U.putOrderedInt(this, QTOP, s + 1); + if ((n = s - b) <= 1) { + if ((p = pool) != null) + p.signalWork(p.workQueues, this); + } else if (n >= m) growArray(); } @@ -764,7 +890,7 @@ public class ForkJoinPool extends AbstractExecutorService { if (oldA != null && (oldMask = oldA.length - 1) >= 0 && (t = top) - (b = base) > 0) { int mask = size - 1; - do { + do { // emulate poll from old array, push to new array ForkJoinTask x; int oldj = ((b & oldMask) << ASHIFT) + ABASE; int j = ((b & mask) << ASHIFT) + ABASE; @@ -789,7 +915,7 @@ public class ForkJoinPool extends AbstractExecutorService { if ((t = (ForkJoinTask)U.getObject(a, j)) == null) break; if (U.compareAndSwapObject(a, j, t, null)) { - top = s; + U.putOrderedInt(this, QTOP, s); return t; } } @@ -800,7 +926,7 @@ public class ForkJoinPool extends AbstractExecutorService { /** * Takes a task in FIFO order if b is base of queue and a task * can be claimed without contention. Specialized versions - * appear in ForkJoinPool methods scan and tryHelpStealer. + * appear in ForkJoinPool methods scan and helpStealer. */ final ForkJoinTask pollAt(int b) { ForkJoinTask t; ForkJoinTask[] a; @@ -808,7 +934,7 @@ public class ForkJoinPool extends AbstractExecutorService { int j = (((a.length - 1) & b) << ASHIFT) + ABASE; if ((t = (ForkJoinTask)U.getObjectVolatile(a, j)) != null && base == b && U.compareAndSwapObject(a, j, t, null)) { - U.putOrderedInt(this, QBASE, b + 1); + base = b + 1; return t; } } @@ -823,16 +949,15 @@ public class ForkJoinPool extends AbstractExecutorService { while ((b = base) - top < 0 && (a = array) != null) { int j = (((a.length - 1) & b) << ASHIFT) + ABASE; t = (ForkJoinTask)U.getObjectVolatile(a, j); - if (t != null) { - if (U.compareAndSwapObject(a, j, t, null)) { - U.putOrderedInt(this, QBASE, b + 1); - return t; + if (base == b) { + if (t != null) { + if (U.compareAndSwapObject(a, j, t, null)) { + base = b + 1; + return t; + } } - } - else if (base == b) { - if (b + 1 == top) + else if (b + 1 == top) // now empty break; - Thread.yield(); // wait for lagging update (very rare) } } return null; @@ -842,7 +967,7 @@ public class ForkJoinPool extends AbstractExecutorService { * Takes next task, if one exists, in order specified by mode. */ final ForkJoinTask nextLocalTask() { - return mode == 0 ? pop() : poll(); + return (config & FIFO_QUEUE) == 0 ? pop() : poll(); } /** @@ -852,7 +977,7 @@ public class ForkJoinPool extends AbstractExecutorService { ForkJoinTask[] a = array; int m; if (a == null || (m = a.length - 1) < 0) return null; - int i = mode == 0 ? top - 1 : base; + int i = (config & FIFO_QUEUE) == 0 ? top - 1 : base; int j = ((i & m) << ASHIFT) + ABASE; return (ForkJoinTask)U.getObjectVolatile(a, j); } @@ -860,13 +985,13 @@ public class ForkJoinPool extends AbstractExecutorService { /** * Pops the given task only if it is at the current top. * (A shared version is available only via FJP.tryExternalUnpush) - */ + */ final boolean tryUnpush(ForkJoinTask t) { ForkJoinTask[] a; int s; if ((a = array) != null && (s = top) != base && U.compareAndSwapObject (a, (((a.length - 1) & --s) << ASHIFT) + ABASE, t, null)) { - top = s; + U.putOrderedInt(this, QTOP, s); return true; } return false; @@ -876,9 +1001,16 @@ public class ForkJoinPool extends AbstractExecutorService { * Removes and cancels all known tasks, ignoring any exceptions. */ final void cancelAll() { - ForkJoinTask.cancelIgnoringExceptions(currentJoin); - ForkJoinTask.cancelIgnoringExceptions(currentSteal); - for (ForkJoinTask t; (t = poll()) != null; ) + ForkJoinTask t; + if ((t = currentJoin) != null) { + currentJoin = null; + ForkJoinTask.cancelIgnoringExceptions(t); + } + if ((t = currentSteal) != null) { + currentSteal = null; + ForkJoinTask.cancelIgnoringExceptions(t); + } + while ((t = poll()) != null) ForkJoinTask.cancelIgnoringExceptions(t); } @@ -893,167 +1025,186 @@ public class ForkJoinPool extends AbstractExecutorService { } /** - * Executes a top-level task and any local tasks remaining - * after execution. + * Removes and executes all local tasks. If LIFO, invokes + * pollAndExecAll. Otherwise implements a specialized pop loop + * to exec until empty. */ - final void runTask(ForkJoinTask task) { - if ((currentSteal = task) != null) { - ForkJoinWorkerThread thread; - task.doExec(); - ForkJoinTask[] a = array; - int md = mode; - ++nsteals; - currentSteal = null; - if (md != 0) - pollAndExecAll(); - else if (a != null) { - int s, m = a.length - 1; - ForkJoinTask t; - while ((s = top - 1) - base >= 0 && - (t = (ForkJoinTask)U.getAndSetObject - (a, ((m & s) << ASHIFT) + ABASE, null)) != null) { - top = s; + final void execLocalTasks() { + int b = base, m, s; + ForkJoinTask[] a = array; + if (b - (s = top - 1) <= 0 && a != null && + (m = a.length - 1) >= 0) { + if ((config & FIFO_QUEUE) == 0) { + for (ForkJoinTask t;;) { + if ((t = (ForkJoinTask)U.getAndSetObject + (a, ((m & s) << ASHIFT) + ABASE, null)) == null) + break; + U.putOrderedInt(this, QTOP, s); t.doExec(); + if (base - (s = top - 1) > 0) + break; } } - if ((thread = owner) != null) // no need to do in finally clause + else + pollAndExecAll(); + } + } + + /** + * Executes the given task and any remaining local tasks. + */ + final void runTask(ForkJoinTask task) { + if (task != null) { + scanState &= ~SCANNING; // mark as busy + (currentSteal = task).doExec(); + U.putOrderedObject(this, QCURRENTSTEAL, null); // release for GC + execLocalTasks(); + ForkJoinWorkerThread thread = owner; + if (++nsteals < 0) // collect on overflow + transferStealCount(pool); + scanState |= SCANNING; + if (thread != null) thread.afterTopLevelExec(); } } + /** + * Adds steal count to pool stealCounter if it exists, and resets. + */ + final void transferStealCount(ForkJoinPool p) { + AtomicLong sc; + if (p != null && (sc = p.stealCounter) != null) { + int s = nsteals; + nsteals = 0; // if negative, correct for overflow + sc.getAndAdd((long)(s < 0 ? Integer.MAX_VALUE : s)); + } + } + /** * If present, removes from queue and executes the given task, - * or any other cancelled task. Returns (true) on any CAS - * or consistency check failure so caller can retry. + * or any other cancelled task. Used only by awaitJoin. * - * @return false if no progress can be made, else true + * @return true if queue empty and task not known to be done */ final boolean tryRemoveAndExec(ForkJoinTask task) { - boolean stat; ForkJoinTask[] a; int m, s, b, n; - if (task != null && (a = array) != null && (m = a.length - 1) >= 0 && - (n = (s = top) - (b = base)) > 0) { - boolean removed = false, empty = true; - stat = true; - for (ForkJoinTask t;;) { // traverse from s to b - long j = ((--s & m) << ASHIFT) + ABASE; - t = (ForkJoinTask)U.getObject(a, j); - if (t == null) // inconsistent length - break; - else if (t == task) { - if (s + 1 == top) { // pop - if (!U.compareAndSwapObject(a, j, task, null)) - break; - top = s; - removed = true; + if ((a = array) != null && (m = a.length - 1) >= 0 && + task != null) { + while ((n = (s = top) - (b = base)) > 0) { + for (ForkJoinTask t;;) { // traverse from s to b + long j = ((--s & m) << ASHIFT) + ABASE; + if ((t = (ForkJoinTask)U.getObject(a, j)) == null) + return s + 1 == top; // shorter than expected + else if (t == task) { + boolean removed = false; + if (s + 1 == top) { // pop + if (U.compareAndSwapObject(a, j, task, null)) { + U.putOrderedInt(this, QTOP, s); + removed = true; + } + } + else if (base == b) // replace with proxy + removed = U.compareAndSwapObject( + a, j, task, new EmptyTask()); + if (removed) + task.doExec(); + break; } - else if (base == b) // replace with proxy - removed = U.compareAndSwapObject(a, j, task, - new EmptyTask()); - break; - } - else if (t.status >= 0) - empty = false; - else if (s + 1 == top) { // pop and throw away - if (U.compareAndSwapObject(a, j, t, null)) - top = s; - break; - } - if (--n == 0) { - if (!empty && base == b) - stat = false; - break; + else if (t.status < 0 && s + 1 == top) { + if (U.compareAndSwapObject(a, j, t, null)) + U.putOrderedInt(this, QTOP, s); + break; // was cancelled + } + if (--n == 0) + return false; } + if (task.status < 0) + return false; } - if (removed) - task.doExec(); } - else - stat = false; - return stat; + return true; } /** - * Tries to poll for and execute the given task or any other - * task in its CountedCompleter computation. + * Pops task if in the same CC computation as the given task, + * in either shared or owned mode. Used only by helpComplete. */ - final boolean pollAndExecCC(CountedCompleter root) { - ForkJoinTask[] a; int b; Object o; CountedCompleter t, r; - if ((b = base) - top < 0 && (a = array) != null) { + final CountedCompleter popCC(CountedCompleter task, int mode) { + int s; ForkJoinTask[] a; Object o; + if (base - (s = top) < 0 && (a = array) != null) { + long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; + if ((o = U.getObjectVolatile(a, j)) != null && + (o instanceof CountedCompleter)) { + CountedCompleter t = (CountedCompleter)o; + for (CountedCompleter r = t;;) { + if (r == task) { + if (mode < 0) { // must lock + if (U.compareAndSwapInt(this, QLOCK, 0, 1)) { + if (top == s && array == a && + U.compareAndSwapObject(a, j, t, null)) { + U.putOrderedInt(this, QTOP, s - 1); + U.putOrderedInt(this, QLOCK, 0); + return t; + } + U.compareAndSwapInt(this, QLOCK, 1, 0); + } + } + else if (U.compareAndSwapObject(a, j, t, null)) { + U.putOrderedInt(this, QTOP, s - 1); + return t; + } + break; + } + else if ((r = r.completer) == null) // try parent + break; + } + } + } + return null; + } + + /** + * Steals and runs a task in the same CC computation as the + * given task if one exists and can be taken without + * contention. Otherwise returns a checksum/control value for + * use by method helpComplete. + * + * @return 1 if successful, 2 if retryable (lost to another + * stealer), -1 if non-empty but no matching task found, else + * the base index, forced negative. + */ + final int pollAndExecCC(CountedCompleter task) { + int b, h; ForkJoinTask[] a; Object o; + if ((b = base) - top >= 0 || (a = array) == null) + h = b | Integer.MIN_VALUE; // to sense movement on re-poll + else { long j = (((a.length - 1) & b) << ASHIFT) + ABASE; if ((o = U.getObjectVolatile(a, j)) == null) - return true; // retry - if (o instanceof CountedCompleter) { - for (t = (CountedCompleter)o, r = t;;) { - if (r == root) { + h = 2; // retryable + else if (!(o instanceof CountedCompleter)) + h = -1; // unmatchable + else { + CountedCompleter t = (CountedCompleter)o; + for (CountedCompleter r = t;;) { + if (r == task) { if (base == b && U.compareAndSwapObject(a, j, t, null)) { - U.putOrderedInt(this, QBASE, b + 1); + base = b + 1; t.doExec(); + h = 1; // success } - return true; - } - else if ((r = r.completer) == null) - break; // not part of root computation - } - } - } - return false; - } - - /** - * Tries to pop and execute the given task or any other task - * in its CountedCompleter computation. - */ - final boolean externalPopAndExecCC(CountedCompleter root) { - ForkJoinTask[] a; int s; Object o; CountedCompleter t, r; - if (base - (s = top) < 0 && (a = array) != null) { - long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; - if ((o = U.getObject(a, j)) instanceof CountedCompleter) { - for (t = (CountedCompleter)o, r = t;;) { - if (r == root) { - if (U.compareAndSwapInt(this, QLOCK, 0, 1)) { - if (top == s && array == a && - U.compareAndSwapObject(a, j, t, null)) { - top = s - 1; - qlock = 0; - t.doExec(); - } - else - qlock = 0; - } - return true; - } - else if ((r = r.completer) == null) + else + h = 2; // lost CAS break; - } - } - } - return false; - } - - /** - * Internal version - */ - final boolean internalPopAndExecCC(CountedCompleter root) { - ForkJoinTask[] a; int s; Object o; CountedCompleter t, r; - if (base - (s = top) < 0 && (a = array) != null) { - long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; - if ((o = U.getObject(a, j)) instanceof CountedCompleter) { - for (t = (CountedCompleter)o, r = t;;) { - if (r == root) { - if (U.compareAndSwapObject(a, j, t, null)) { - top = s - 1; - t.doExec(); - } - return true; } - else if ((r = r.completer) == null) + else if ((r = r.completer) == null) { + h = -1; // unmatched break; + } } } } - return false; + return h; } /** @@ -1061,28 +1212,31 @@ public class ForkJoinPool extends AbstractExecutorService { */ final boolean isApparentlyUnblocked() { Thread wt; Thread.State s; - return (eventCount >= 0 && + return (scanState >= 0 && (wt = owner) != null && (s = wt.getState()) != Thread.State.BLOCKED && s != Thread.State.WAITING && s != Thread.State.TIMED_WAITING); } - // Unsafe mechanics + // Unsafe mechanics. Note that some are (and must be) the same as in FJP private static final sun.misc.Unsafe U; - private static final long QBASE; + private static final int ABASE; + private static final int ASHIFT; + private static final long QTOP; private static final long QLOCK; - private static final int ABASE; - private static final int ASHIFT; + private static final long QCURRENTSTEAL; static { try { U = sun.misc.Unsafe.getUnsafe(); - Class k = WorkQueue.class; + Class wk = WorkQueue.class; Class ak = ForkJoinTask[].class; - QBASE = U.objectFieldOffset - (k.getDeclaredField("base")); + QTOP = U.objectFieldOffset + (wk.getDeclaredField("top")); QLOCK = U.objectFieldOffset - (k.getDeclaredField("qlock")); + (wk.getDeclaredField("qlock")); + QCURRENTSTEAL = U.objectFieldOffset + (wk.getDeclaredField("currentSteal")); ABASE = U.arrayBaseOffset(ak); int scale = U.arrayIndexScale(ak); if ((scale & (scale - 1)) != 0) @@ -1125,6 +1279,11 @@ public class ForkJoinPool extends AbstractExecutorService { */ static final int commonParallelism; + /** + * Limit on spare thread construction in tryCompensate. + */ + private static int commonMaxSpares; + /** * Sequence number for creating workerNamePrefix. */ @@ -1138,7 +1297,7 @@ public class ForkJoinPool extends AbstractExecutorService { return ++poolNumberSequence; } - // static constants + // static configuration constants /** * Initial timeout value (in nanoseconds) for the thread @@ -1148,27 +1307,34 @@ public class ForkJoinPool extends AbstractExecutorService { * aggressive shrinkage during most transient stalls (long GCs * etc). */ - private static final long IDLE_TIMEOUT = 2000L * 1000L * 1000L; // 2sec - - /** - * Timeout value when there are more threads than parallelism level - */ - private static final long FAST_IDLE_TIMEOUT = 200L * 1000L * 1000L; + private static final long IDLE_TIMEOUT = 2000L * 1000L * 1000L; // 2sec /** * Tolerance for idle timeouts, to cope with timer undershoots */ - private static final long TIMEOUT_SLOP = 2000000L; + private static final long TIMEOUT_SLOP = 20L * 1000L * 1000L; // 20ms /** - * The maximum stolen->joining link depth allowed in method - * tryHelpStealer. Must be a power of two. Depths for legitimate - * chains are unbounded, but we use a fixed constant to avoid - * (otherwise unchecked) cycles and to bound staleness of - * traversal parameters at the expense of sometimes blocking when - * we could be helping. + * The initial value for commonMaxSpares during static + * initialization unless overridden using System property + * "java.util.concurrent.ForkJoinPool.common.maximumSpares". The + * default value is far in excess of normal requirements, but also + * far short of MAX_CAP and typical OS thread limits, so allows + * JVMs to catch misuse/abuse before running out of resources + * needed to do so. */ - private static final int MAX_HELP = 64; + private static final int DEFAULT_COMMON_MAX_SPARES = 256; + + /** + * Number of times to spin-wait before blocking. The spins (in + * awaitRunStateLock and awaitWork) currently use randomized + * spins. If/when MWAIT-like intrinsics becomes available, they + * may allow quieter spinning. The value of SPINS must be a power + * of two, at least 4. The current value causes spinning for a + * small fraction of typical context-switch times, well worthwhile + * given the typical likelihoods that blocking is not necessary. + */ + private static final int SPINS = 1 << 11; /** * Increment for seed generators. See class ThreadLocal for @@ -1177,209 +1343,212 @@ public class ForkJoinPool extends AbstractExecutorService { private static final int SEED_INCREMENT = 0x9e3779b9; /* - * Bits and masks for control variables + * Bits and masks for field ctl, packed with 4 16 bit subfields: + * AC: Number of active running workers minus target parallelism + * TC: Number of total workers minus target parallelism + * SS: version count and status of top waiting thread + * ID: poolIndex of top of Treiber stack of waiters * - * Field ctl is a long packed with: - * AC: Number of active running workers minus target parallelism (16 bits) - * TC: Number of total workers minus target parallelism (16 bits) - * ST: true if pool is terminating (1 bit) - * EC: the wait count of top waiting thread (15 bits) - * ID: poolIndex of top of Treiber stack of waiters (16 bits) + * When convenient, we can extract the lower 32 stack top bits + * (including version bits) as sp=(int)ctl. The offsets of counts + * by the target parallelism and the positionings of fields makes + * it possible to perform the most common checks via sign tests of + * fields: When ac is negative, there are not enough active + * workers, when tc is negative, there are not enough total + * workers. When sp is non-zero, there are waiting workers. To + * deal with possibly negative fields, we use casts in and out of + * "short" and/or signed shifts to maintain signedness. * - * When convenient, we can extract the upper 32 bits of counts and - * the lower 32 bits of queue state, u = (int)(ctl >>> 32) and e = - * (int)ctl. The ec field is never accessed alone, but always - * together with id and st. The offsets of counts by the target - * parallelism and the positionings of fields makes it possible to - * perform the most common checks via sign tests of fields: When - * ac is negative, there are not enough active workers, when tc is - * negative, there are not enough total workers, and when e is - * negative, the pool is terminating. To deal with these possibly - * negative fields, we use casts in and out of "short" and/or - * signed shifts to maintain signedness. - * - * When a thread is queued (inactivated), its eventCount field is - * set negative, which is the only way to tell if a worker is - * prevented from executing tasks, even though it must continue to - * scan for them to avoid queuing races. Note however that - * eventCount updates lag releases so usage requires care. - * - * Field plock is an int packed with: - * SHUTDOWN: true if shutdown is enabled (1 bit) - * SEQ: a sequence lock, with PL_LOCK bit set if locked (30 bits) - * SIGNAL: set when threads may be waiting on the lock (1 bit) - * - * The sequence number enables simple consistency checks: - * Staleness of read-only operations on the workQueues array can - * be checked by comparing plock before vs after the reads. + * Because it occupies uppermost bits, we can add one active count + * using getAndAddLong of AC_UNIT, rather than CAS, when returning + * from a blocked join. Other updates entail multiple subfields + * and masking, requiring CAS. */ - // bit positions/shifts for fields + // Lower and upper word masks + private static final long SP_MASK = 0xffffffffL; + private static final long UC_MASK = ~SP_MASK; + + // Active counts private static final int AC_SHIFT = 48; + private static final long AC_UNIT = 0x0001L << AC_SHIFT; + private static final long AC_MASK = 0xffffL << AC_SHIFT; + + // Total counts private static final int TC_SHIFT = 32; - private static final int ST_SHIFT = 31; - private static final int EC_SHIFT = 16; + private static final long TC_UNIT = 0x0001L << TC_SHIFT; + private static final long TC_MASK = 0xffffL << TC_SHIFT; + private static final long ADD_WORKER = 0x0001L << (TC_SHIFT + 15); // sign - // bounds - private static final int SMASK = 0xffff; // short bits - private static final int MAX_CAP = 0x7fff; // max #workers - 1 - private static final int EVENMASK = 0xfffe; // even short bits - private static final int SQMASK = 0x007e; // max 64 (even) slots - private static final int SHORT_SIGN = 1 << 15; - private static final int INT_SIGN = 1 << 31; - - // masks - private static final long STOP_BIT = 0x0001L << ST_SHIFT; - private static final long AC_MASK = ((long)SMASK) << AC_SHIFT; - private static final long TC_MASK = ((long)SMASK) << TC_SHIFT; - - // units for incrementing and decrementing - private static final long TC_UNIT = 1L << TC_SHIFT; - private static final long AC_UNIT = 1L << AC_SHIFT; - - // masks and units for dealing with u = (int)(ctl >>> 32) - private static final int UAC_SHIFT = AC_SHIFT - 32; - private static final int UTC_SHIFT = TC_SHIFT - 32; - private static final int UAC_MASK = SMASK << UAC_SHIFT; - private static final int UTC_MASK = SMASK << UTC_SHIFT; - private static final int UAC_UNIT = 1 << UAC_SHIFT; - private static final int UTC_UNIT = 1 << UTC_SHIFT; - - // masks and units for dealing with e = (int)ctl - private static final int E_MASK = 0x7fffffff; // no STOP_BIT - private static final int E_SEQ = 1 << EC_SHIFT; - - // plock bits - private static final int SHUTDOWN = 1 << 31; - private static final int PL_LOCK = 2; - private static final int PL_SIGNAL = 1; - private static final int PL_SPINS = 1 << 8; - - // access mode for WorkQueue - static final int LIFO_QUEUE = 0; - static final int FIFO_QUEUE = 1; - static final int SHARED_QUEUE = -1; + // runState bits: SHUTDOWN must be negative, others arbitrary powers of two + private static final int RSLOCK = 1; + private static final int RSIGNAL = 1 << 1; + private static final int STARTED = 1 << 2; + private static final int STOP = 1 << 29; + private static final int TERMINATED = 1 << 30; + private static final int SHUTDOWN = 1 << 31; // Instance fields - volatile long stealCount; // collects worker counts - volatile long ctl; // main pool control - volatile int plock; // shutdown status and seqLock - volatile int indexSeed; // worker/submitter index seed - final short parallelism; // parallelism level - final short mode; // LIFO/FIFO - WorkQueue[] workQueues; // main registry + volatile long ctl; // main pool control + volatile int runState; // lockable status + final int config; // parallelism, mode + int indexSeed; // to generate worker index + volatile WorkQueue[] workQueues; // main registry final ForkJoinWorkerThreadFactory factory; - final UncaughtExceptionHandler ueh; // per-worker UEH - final String workerNamePrefix; // to create worker name string + final UncaughtExceptionHandler ueh; // per-worker UEH + final String workerNamePrefix; // to create worker name string + volatile AtomicLong stealCounter; // also used as sync monitor /** - * Acquires the plock lock to protect worker array and related - * updates. This method is called only if an initial CAS on plock - * fails. This acts as a spinlock for normal cases, but falls back - * to builtin monitor to block when (rarely) needed. This would be - * a terrible idea for a highly contended lock, but works fine as - * a more conservative alternative to a pure spinlock. + * Acquires the runState lock; returns current (locked) runState. */ - private int acquirePlock() { - int spins = PL_SPINS, ps, nps; - for (;;) { - if (((ps = plock) & PL_LOCK) == 0 && - U.compareAndSwapInt(this, PLOCK, ps, nps = ps + PL_LOCK)) - return nps; - else if (spins >= 0) { - if (ThreadLocalRandom.nextSecondarySeed() >= 0) + private int lockRunState() { + int rs; + return ((((rs = runState) & RSLOCK) != 0 || + !U.compareAndSwapInt(this, RUNSTATE, rs, rs |= RSLOCK)) ? + awaitRunStateLock() : rs); + } + + /** + * Spins and/or blocks until runstate lock is available. See + * above for explanation. + */ + private int awaitRunStateLock() { + Object lock; + boolean wasInterrupted = false; + for (int spins = SPINS, r = 0, rs, ns;;) { + if (((rs = runState) & RSLOCK) == 0) { + if (U.compareAndSwapInt(this, RUNSTATE, rs, ns = rs | RSLOCK)) { + if (wasInterrupted) { + try { + Thread.currentThread().interrupt(); + } catch (SecurityException ignore) { + } + } + return ns; + } + } + else if (r == 0) + r = ThreadLocalRandom.nextSecondarySeed(); + else if (spins > 0) { + r ^= r << 6; r ^= r >>> 21; r ^= r << 7; // xorshift + if (r >= 0) --spins; } - else if (U.compareAndSwapInt(this, PLOCK, ps, ps | PL_SIGNAL)) { - synchronized (this) { - if ((plock & PL_SIGNAL) != 0) { + else if ((rs & STARTED) == 0 || (lock = stealCounter) == null) + Thread.yield(); // initialization race + else if (U.compareAndSwapInt(this, RUNSTATE, rs, rs | RSIGNAL)) { + synchronized (lock) { + if ((runState & RSIGNAL) != 0) { try { - wait(); + lock.wait(); } catch (InterruptedException ie) { - try { - Thread.currentThread().interrupt(); - } catch (SecurityException ignore) { - } + if (!(Thread.currentThread() instanceof + ForkJoinWorkerThread)) + wasInterrupted = true; } } else - notifyAll(); + lock.notifyAll(); } } } } /** - * Unlocks and signals any thread waiting for plock. Called only - * when CAS of seq value for unlock fails. + * Unlocks and sets runState to newRunState. + * + * @param oldRunState a value returned from lockRunState + * @param newRunState the next value (must have lock bit clear). */ - private void releasePlock(int ps) { - plock = ps; - synchronized (this) { notifyAll(); } - } - - /** - * Tries to create and start one worker if fewer than target - * parallelism level exist. Adjusts counts etc on failure. - */ - private void tryAddWorker() { - long c; int u, e; - while ((u = (int)((c = ctl) >>> 32)) < 0 && - (u & SHORT_SIGN) != 0 && (e = (int)c) >= 0) { - long nc = ((long)(((u + UTC_UNIT) & UTC_MASK) | - ((u + UAC_UNIT) & UAC_MASK)) << 32) | (long)e; - if (U.compareAndSwapLong(this, CTL, c, nc)) { - ForkJoinWorkerThreadFactory fac; - Throwable ex = null; - ForkJoinWorkerThread wt = null; - try { - if ((fac = factory) != null && - (wt = fac.newThread(this)) != null) { - wt.start(); - break; - } - } catch (Throwable rex) { - ex = rex; - } - deregisterWorker(wt, ex); - break; - } + private void unlockRunState(int oldRunState, int newRunState) { + if (!U.compareAndSwapInt(this, RUNSTATE, oldRunState, newRunState)) { + Object lock = stealCounter; + runState = newRunState; // clears RSIGNAL bit + if (lock != null) + synchronized (lock) { lock.notifyAll(); } } } - // Registering and deregistering workers + // Creating, registering and deregistering workers /** - * Callback from ForkJoinWorkerThread to establish and record its - * WorkQueue. To avoid scanning bias due to packing entries in - * front of the workQueues array, we treat the array as a simple - * power-of-two hash table using per-thread seed as hash, - * expanding as needed. + * Tries to construct and start one worker. Assumes that total + * count has already been incremented as a reservation. Invokes + * deregisterWorker on any failure. + * + * @return true if successful + */ + private boolean createWorker() { + ForkJoinWorkerThreadFactory fac = factory; + Throwable ex = null; + ForkJoinWorkerThread wt = null; + try { + if (fac != null && (wt = fac.newThread(this)) != null) { + wt.start(); + return true; + } + } catch (Throwable rex) { + ex = rex; + } + deregisterWorker(wt, ex); + return false; + } + + /** + * Tries to add one worker, incrementing ctl counts before doing + * so, relying on createWorker to back out on failure. + * + * @param c incoming ctl value, with total count negative and no + * idle workers. On CAS failure, c is refreshed and retried if + * this holds (otherwise, a new worker is not needed). + */ + private void tryAddWorker(long c) { + boolean add = false; + do { + long nc = ((AC_MASK & (c + AC_UNIT)) | + (TC_MASK & (c + TC_UNIT))); + if (ctl == c) { + int rs, stop; // check if terminating + if ((stop = (rs = lockRunState()) & STOP) == 0) + add = U.compareAndSwapLong(this, CTL, c, nc); + unlockRunState(rs, rs & ~RSLOCK); + if (stop != 0) + break; + if (add) { + createWorker(); + break; + } + } + } while (((c = ctl) & ADD_WORKER) != 0L && (int)c == 0); + } + + /** + * Callback from ForkJoinWorkerThread constructor to establish and + * record its WorkQueue. * * @param wt the worker thread * @return the worker's queue */ final WorkQueue registerWorker(ForkJoinWorkerThread wt) { - UncaughtExceptionHandler handler; WorkQueue[] ws; int s, ps; - wt.setDaemon(true); + UncaughtExceptionHandler handler; + wt.setDaemon(true); // configure thread if ((handler = ueh) != null) wt.setUncaughtExceptionHandler(handler); - do {} while (!U.compareAndSwapInt(this, INDEXSEED, s = indexSeed, - s += SEED_INCREMENT) || - s == 0); // skip 0 - WorkQueue w = new WorkQueue(this, wt, mode, s); - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); + WorkQueue w = new WorkQueue(this, wt); + int i = 0; // assign a pool index + int mode = config & MODE_MASK; + int rs = lockRunState(); try { - if ((ws = workQueues) != null) { // skip if shutting down - int n = ws.length, m = n - 1; - int r = (s << 1) | 1; // use odd-numbered indices - if (ws[r &= m] != null) { // collision - int probes = 0; // step by approx half size + WorkQueue[] ws; int n; // skip if no array + if ((ws = workQueues) != null && (n = ws.length) > 0) { + int s = indexSeed += SEED_INCREMENT; // unlikely to collide + int m = n - 1; + i = ((s << 1) | 1) & m; // odd-numbered indices + if (ws[i] != null) { // collision + int probes = 0; // step by approx half n int step = (n <= 4) ? 2 : ((n >>> 1) & EVENMASK) + 2; - while (ws[r = (r + step) & m] != null) { + while (ws[i = (i + step) & m] != null) { if (++probes >= n) { workQueues = ws = Arrays.copyOf(ws, n <<= 1); m = n - 1; @@ -1387,15 +1556,15 @@ public class ForkJoinPool extends AbstractExecutorService { } } } - w.poolIndex = (short)r; - w.eventCount = r; // volatile write orders - ws[r] = w; + w.hint = s; // use as random seed + w.config = i | mode; + w.scanState = i; // publication fence + ws[i] = w; } } finally { - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); + unlockRunState(rs, rs & ~RSLOCK); } - wt.setName(workerNamePrefix.concat(Integer.toString(w.poolIndex >>> 1))); + wt.setName(workerNamePrefix.concat(Integer.toString(i >>> 1))); return w; } @@ -1411,384 +1580,322 @@ public class ForkJoinPool extends AbstractExecutorService { final void deregisterWorker(ForkJoinWorkerThread wt, Throwable ex) { WorkQueue w = null; if (wt != null && (w = wt.workQueue) != null) { - int ps; - w.qlock = -1; // ensure set - U.getAndAddLong(this, STEALCOUNT, w.nsteals); // collect steals - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); - try { - int idx = w.poolIndex; - WorkQueue[] ws = workQueues; - if (ws != null && idx >= 0 && idx < ws.length && ws[idx] == w) - ws[idx] = null; - } finally { - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); - } + WorkQueue[] ws; // remove index from array + int idx = w.config & SMASK; + int rs = lockRunState(); + if ((ws = workQueues) != null && ws.length > idx && ws[idx] == w) + ws[idx] = null; + unlockRunState(rs, rs & ~RSLOCK); } - - long c; // adjust ctl counts + long c; // decrement counts do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, (((c - AC_UNIT) & AC_MASK) | - ((c - TC_UNIT) & TC_MASK) | - (c & ~(AC_MASK|TC_MASK))))); - - if (!tryTerminate(false, false) && w != null && w.array != null) { - w.cancelAll(); // cancel remaining tasks - WorkQueue[] ws; WorkQueue v; Thread p; int u, i, e; - while ((u = (int)((c = ctl) >>> 32)) < 0 && (e = (int)c) >= 0) { - if (e > 0) { // activate or create replacement - if ((ws = workQueues) == null || - (i = e & SMASK) >= ws.length || - (v = ws[i]) == null) - break; - long nc = (((long)(v.nextWait & E_MASK)) | - ((long)(u + UAC_UNIT) << 32)); - if (v.eventCount != (e | INT_SIGN)) - break; - if (U.compareAndSwapLong(this, CTL, c, nc)) { - v.eventCount = (e + E_SEQ) & E_MASK; - if ((p = v.parker) != null) - U.unpark(p); - break; - } - } - else { - if ((short)u < 0) - tryAddWorker(); - break; - } - } + (this, CTL, c = ctl, ((AC_MASK & (c - AC_UNIT)) | + (TC_MASK & (c - TC_UNIT)) | + (SP_MASK & c)))); + if (w != null) { + w.qlock = -1; // ensure set + w.transferStealCount(this); + w.cancelAll(); // cancel remaining tasks } - if (ex == null) // help clean refs on way out + for (;;) { // possibly replace + WorkQueue[] ws; int m, sp; + if (tryTerminate(false, false) || w == null || w.array == null || + (runState & STOP) != 0 || (ws = workQueues) == null || + (m = ws.length - 1) < 0) // already terminating + break; + if ((sp = (int)(c = ctl)) != 0) { // wake up replacement + if (tryRelease(c, ws[sp & m], AC_UNIT)) + break; + } + else if (ex != null && (c & ADD_WORKER) != 0L) { + tryAddWorker(c); // create replacement + break; + } + else // don't need replacement + break; + } + if (ex == null) // help clean on way out ForkJoinTask.helpExpungeStaleExceptions(); - else // rethrow + else // rethrow ForkJoinTask.rethrow(ex); } - // Submissions - - /** - * Unless shutting down, adds the given task to a submission queue - * at submitter's current queue index (modulo submission - * range). Only the most common path is directly handled in this - * method. All others are relayed to fullExternalPush. - * - * @param task the task. Caller must ensure non-null. - */ - final void externalPush(ForkJoinTask task) { - WorkQueue q; int m, s, n, am; ForkJoinTask[] a; - int r = ThreadLocalRandom.getProbe(); - int ps = plock; - WorkQueue[] ws = workQueues; - if (ps > 0 && ws != null && (m = (ws.length - 1)) >= 0 && - (q = ws[m & r & SQMASK]) != null && r != 0 && - U.compareAndSwapInt(q, QLOCK, 0, 1)) { // lock - if ((a = q.array) != null && - (am = a.length - 1) > (n = (s = q.top) - q.base)) { - int j = ((am & s) << ASHIFT) + ABASE; - U.putOrderedObject(a, j, task); - q.top = s + 1; // push on to deque - q.qlock = 0; - if (n <= 1) - signalWork(ws, q); - return; - } - q.qlock = 0; - } - fullExternalPush(task); - } - - /** - * Full version of externalPush. This method is called, among - * other times, upon the first submission of the first task to the - * pool, so must perform secondary initialization. It also - * detects first submission by an external thread by looking up - * its ThreadLocal, and creates a new shared queue if the one at - * index if empty or contended. The plock lock body must be - * exception-free (so no try/finally) so we optimistically - * allocate new queues outside the lock and throw them away if - * (very rarely) not needed. - * - * Secondary initialization occurs when plock is zero, to create - * workQueue array and set plock to a valid value. This lock body - * must also be exception-free. Because the plock seq value can - * eventually wrap around zero, this method harmlessly fails to - * reinitialize if workQueues exists, while still advancing plock. - */ - private void fullExternalPush(ForkJoinTask task) { - int r; - if ((r = ThreadLocalRandom.getProbe()) == 0) { - ThreadLocalRandom.localInit(); - r = ThreadLocalRandom.getProbe(); - } - for (;;) { - WorkQueue[] ws; WorkQueue q; int ps, m, k; - boolean move = false; - if ((ps = plock) < 0) - throw new RejectedExecutionException(); - else if (ps == 0 || (ws = workQueues) == null || - (m = ws.length - 1) < 0) { // initialize workQueues - int p = parallelism; // find power of two table size - int n = (p > 1) ? p - 1 : 1; // ensure at least 2 slots - n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; - n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1; - WorkQueue[] nws = ((ws = workQueues) == null || ws.length == 0 ? - new WorkQueue[n] : null); - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - if (((ws = workQueues) == null || ws.length == 0) && nws != null) - workQueues = nws; - int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); - } - else if ((q = ws[k = r & m & SQMASK]) != null) { - if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) { - ForkJoinTask[] a = q.array; - int s = q.top; - boolean submitted = false; - try { // locked version of push - if ((a != null && a.length > s + 1 - q.base) || - (a = q.growArray()) != null) { // must presize - int j = (((a.length - 1) & s) << ASHIFT) + ABASE; - U.putOrderedObject(a, j, task); - q.top = s + 1; - submitted = true; - } - } finally { - q.qlock = 0; // unlock - } - if (submitted) { - signalWork(ws, q); - return; - } - } - move = true; // move on failure - } - else if (((ps = plock) & PL_LOCK) == 0) { // create new queue - q = new WorkQueue(this, null, SHARED_QUEUE, r); - q.poolIndex = (short)k; - if (((ps = plock) & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - if ((ws = workQueues) != null && k < ws.length && ws[k] == null) - ws[k] = q; - int nps = (ps & SHUTDOWN) | ((ps + PL_LOCK) & ~SHUTDOWN); - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); - } - else - move = true; // move if busy - if (move) - r = ThreadLocalRandom.advanceProbe(r); - } - } - - // Maintaining ctl counts - - /** - * Increments active count; mainly called upon return from blocking. - */ - final void incrementActiveCount() { - long c; - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, ((c & ~AC_MASK) | - ((c & AC_MASK) + AC_UNIT)))); - } + // Signalling /** * Tries to create or activate a worker if too few are active. * * @param ws the worker array to use to find signallees - * @param q if non-null, the queue holding tasks to be processed + * @param q a WorkQueue --if non-null, don't retry if now empty */ final void signalWork(WorkQueue[] ws, WorkQueue q) { - for (;;) { - long c; int e, u, i; WorkQueue w; Thread p; - if ((u = (int)((c = ctl) >>> 32)) >= 0) - break; - if ((e = (int)c) <= 0) { - if ((short)u < 0) - tryAddWorker(); + long c; int sp, i; WorkQueue v; Thread p; + while ((c = ctl) < 0L) { // too few active + if ((sp = (int)c) == 0) { // no idle workers + if ((c & ADD_WORKER) != 0L) // too few workers + tryAddWorker(c); break; } - if (ws == null || ws.length <= (i = e & SMASK) || - (w = ws[i]) == null) + if (ws == null) // unstarted/terminated break; - long nc = (((long)(w.nextWait & E_MASK)) | - ((long)(u + UAC_UNIT)) << 32); - int ne = (e + E_SEQ) & E_MASK; - if (w.eventCount == (e | INT_SIGN) && - U.compareAndSwapLong(this, CTL, c, nc)) { - w.eventCount = ne; - if ((p = w.parker) != null) + if (ws.length <= (i = sp & SMASK)) // terminated + break; + if ((v = ws[i]) == null) // terminating + break; + int vs = (sp + SS_SEQ) & ~INACTIVE; // next scanState + int d = sp - v.scanState; // screen CAS + long nc = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & v.stackPred); + if (d == 0 && U.compareAndSwapLong(this, CTL, c, nc)) { + v.scanState = vs; // activate v + if ((p = v.parker) != null) U.unpark(p); break; } - if (q != null && q.base >= q.top) + if (q != null && q.base == q.top) // no more work break; } } + /** + * Signals and releases worker v if it is top of idle worker + * stack. This performs a one-shot version of signalWork only if + * there is (apparently) at least one idle worker. + * + * @param c incoming ctl value + * @param v if non-null, a worker + * @param inc the increment to active count (zero when compensating) + * @return true if successful + */ + private boolean tryRelease(long c, WorkQueue v, long inc) { + int sp = (int)c, vs = (sp + SS_SEQ) & ~INACTIVE; Thread p; + if (v != null && v.scanState == sp) { // v is at top of stack + long nc = (UC_MASK & (c + inc)) | (SP_MASK & v.stackPred); + if (U.compareAndSwapLong(this, CTL, c, nc)) { + v.scanState = vs; + if ((p = v.parker) != null) + U.unpark(p); + return true; + } + } + return false; + } + // Scanning for tasks /** * Top-level runloop for workers, called by ForkJoinWorkerThread.run. */ final void runWorker(WorkQueue w) { - w.growArray(); // allocate queue - for (int r = w.hint; scan(w, r) == 0; ) { + w.growArray(); // allocate queue + int seed = w.hint; // initially holds randomization hint + int r = (seed == 0) ? 1 : seed; // avoid 0 for xorShift + for (ForkJoinTask t;;) { + if ((t = scan(w, r)) != null) + w.runTask(t); + else if (!awaitWork(w, r)) + break; r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift } } /** - * Scans for and, if found, runs one task, else possibly - * inactivates the worker. This method operates on single reads of - * volatile state and is designed to be re-invoked continuously, - * in part because it returns upon detecting inconsistencies, - * contention, or state changes that indicate possible success on - * re-invocation. - * - * The scan searches for tasks across queues starting at a random - * index, checking each at least twice. The scan terminates upon - * either finding a non-empty queue, or completing the sweep. If - * the worker is not inactivated, it takes and runs a task from - * this queue. Otherwise, if not activated, it tries to activate - * itself or some other worker by signalling. On failure to find a - * task, returns (for retry) if pool state may have changed during - * an empty scan, or tries to inactivate if active, else possibly - * blocks or terminates via method awaitWork. + * Scans for and tries to steal a top-level task. Scans start at a + * random location, randomly moving on apparent contention, + * otherwise continuing linearly until reaching two consecutive + * empty passes over all queues with the same checksum (summing + * each base index of each queue, that moves on each steal), at + * which point the worker tries to inactivate and then re-scans, + * attempting to re-activate (itself or some other worker) if + * finding a task; otherwise returning null to await work. Scans + * otherwise touch as little memory as possible, to reduce + * disruption on other scanning threads. * * @param w the worker (via its WorkQueue) * @param r a random seed - * @return worker qlock status if would have waited, else 0 + * @return a task, or null if none found */ - private final int scan(WorkQueue w, int r) { + private ForkJoinTask scan(WorkQueue w, int r) { WorkQueue[] ws; int m; - long c = ctl; // for consistency check - if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && w != null) { - for (int j = m + m + 1, ec = w.eventCount;;) { - WorkQueue q; int b, e; ForkJoinTask[] a; ForkJoinTask t; - if ((q = ws[(r - j) & m]) != null && - (b = q.base) - q.top < 0 && (a = q.array) != null) { - long i = (((a.length - 1) & b) << ASHIFT) + ABASE; - if ((t = ((ForkJoinTask) - U.getObjectVolatile(a, i))) != null) { - if (ec < 0) - helpRelease(c, ws, w, q, b); - else if (q.base == b && - U.compareAndSwapObject(a, i, t, null)) { - U.putOrderedInt(q, QBASE, b + 1); - if ((b + 1) - q.top < 0) - signalWork(ws, q); - w.runTask(t); + if ((ws = workQueues) != null && (m = ws.length - 1) > 0 && w != null) { + int ss = w.scanState; // initially non-negative + for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) { + WorkQueue q; ForkJoinTask[] a; ForkJoinTask t; + int b, n; long c; + if ((q = ws[k]) != null) { + if ((n = (b = q.base) - q.top) < 0 && + (a = q.array) != null) { // non-empty + long i = (((a.length - 1) & b) << ASHIFT) + ABASE; + if ((t = ((ForkJoinTask) + U.getObjectVolatile(a, i))) != null && + q.base == b) { + if (ss >= 0) { + if (U.compareAndSwapObject(a, i, t, null)) { + q.base = b + 1; + if (n < -1) // signal others + signalWork(ws, q); + return t; + } + } + else if (oldSum == 0 && // try to activate + w.scanState < 0) + tryRelease(c = ctl, ws[m & (int)c], AC_UNIT); } + if (ss < 0) // refresh + ss = w.scanState; + r ^= r << 1; r ^= r >>> 3; r ^= r << 10; + origin = k = r & m; // move and rescan + oldSum = checkSum = 0; + continue; } - break; + checkSum += b; } - else if (--j < 0) { - if ((ec | (e = (int)c)) < 0) // inactive or terminating - return awaitWork(w, c, ec); - else if (ctl == c) { // try to inactivate and enqueue - long nc = (long)ec | ((c - AC_UNIT) & (AC_MASK|TC_MASK)); - w.nextWait = e; - w.eventCount = ec | INT_SIGN; - if (!U.compareAndSwapLong(this, CTL, c, nc)) - w.eventCount = ec; // back out + if ((k = (k + 1) & m) == origin) { // continue until stable + if ((ss >= 0 || (ss == (ss = w.scanState))) && + oldSum == (oldSum = checkSum)) { + if (ss < 0 || w.qlock < 0) // already inactive + break; + int ns = ss | INACTIVE; // try to inactivate + long nc = ((SP_MASK & ns) | + (UC_MASK & ((c = ctl) - AC_UNIT))); + w.stackPred = (int)c; // hold prev stack top + U.putInt(w, QSCANSTATE, ns); + if (U.compareAndSwapLong(this, CTL, c, nc)) + ss = ns; + else + w.scanState = ss; // back out } - break; + checkSum = 0; } } } - return 0; + return null; } /** - * A continuation of scan(), possibly blocking or terminating - * worker w. Returns without blocking if pool state has apparently - * changed since last invocation. Also, if inactivating w has - * caused the pool to become quiescent, checks for pool + * Possibly blocks worker w waiting for a task to steal, or + * returns false if the worker should terminate. If inactivating + * w has caused the pool to become quiescent, checks for pool * termination, and, so long as this is not the only worker, waits - * for event for up to a given duration. On timeout, if ctl has - * not changed, terminates the worker, which will in turn wake up + * for up to a given duration. On timeout, if ctl has not + * changed, terminates the worker, which will in turn wake up * another worker to possibly repeat this process. * * @param w the calling worker - * @param c the ctl value on entry to scan - * @param ec the worker's eventCount on entry to scan + * @param r a random seed (for spins) + * @return false if the worker should terminate */ - private final int awaitWork(WorkQueue w, long c, int ec) { - int stat, ns; long parkTime, deadline; - if ((stat = w.qlock) >= 0 && w.eventCount == ec && ctl == c && - !Thread.interrupted()) { - int e = (int)c; - int u = (int)(c >>> 32); - int d = (u >> UAC_SHIFT) + parallelism; // active count - - if (e < 0 || (d <= 0 && tryTerminate(false, false))) - stat = w.qlock = -1; // pool is terminating - else if ((ns = w.nsteals) != 0) { // collect steals and retry - w.nsteals = 0; - U.getAndAddLong(this, STEALCOUNT, (long)ns); + private boolean awaitWork(WorkQueue w, int r) { + if (w == null || w.qlock < 0) // w is terminating + return false; + for (int pred = w.stackPred, spins = SPINS, ss;;) { + if ((ss = w.scanState) >= 0) + break; + else if (spins > 0) { + r ^= r << 6; r ^= r >>> 21; r ^= r << 7; + if (r >= 0 && --spins == 0) { // randomize spins + WorkQueue v; WorkQueue[] ws; int s, j; AtomicLong sc; + if (pred != 0 && (ws = workQueues) != null && + (j = pred & SMASK) < ws.length && + (v = ws[j]) != null && // see if pred parking + (v.parker == null || v.scanState >= 0)) + spins = SPINS; // continue spinning + } } - else { - long pc = ((d > 0 || ec != (e | INT_SIGN)) ? 0L : - ((long)(w.nextWait & E_MASK)) | // ctl to restore - ((long)(u + UAC_UNIT)) << 32); - if (pc != 0L) { // timed wait if last waiter - int dc = -(short)(c >>> TC_SHIFT); - parkTime = (dc < 0 ? FAST_IDLE_TIMEOUT: - (dc + 1) * IDLE_TIMEOUT); + else if (w.qlock < 0) // recheck after spins + return false; + else if (!Thread.interrupted()) { + long c, prevctl, parkTime, deadline; + int ac = (int)((c = ctl) >> AC_SHIFT) + (config & SMASK); + if ((ac <= 0 && tryTerminate(false, false)) || + (runState & STOP) != 0) // pool terminating + return false; + if (ac <= 0 && ss == (int)c) { // is last waiter + prevctl = (UC_MASK & (c + AC_UNIT)) | (SP_MASK & pred); + int t = (short)(c >>> TC_SHIFT); // shrink excess spares + if (t > 2 && U.compareAndSwapLong(this, CTL, c, prevctl)) + return false; // else use timed wait + parkTime = IDLE_TIMEOUT * ((t >= 0) ? 1 : 1 - t); deadline = System.nanoTime() + parkTime - TIMEOUT_SLOP; } else - parkTime = deadline = 0L; - if (w.eventCount == ec && ctl == c) { - Thread wt = Thread.currentThread(); - U.putObject(wt, PARKBLOCKER, this); - w.parker = wt; // emulate LockSupport.park - if (w.eventCount == ec && ctl == c) - U.park(false, parkTime); // must recheck before park - w.parker = null; - U.putObject(wt, PARKBLOCKER, null); - if (parkTime != 0L && ctl == c && - deadline - System.nanoTime() <= 0L && - U.compareAndSwapLong(this, CTL, c, pc)) - stat = w.qlock = -1; // shrink pool + prevctl = parkTime = deadline = 0L; + Thread wt = Thread.currentThread(); + U.putObject(wt, PARKBLOCKER, this); // emulate LockSupport + w.parker = wt; + if (w.scanState < 0 && ctl == c) // recheck before park + U.park(false, parkTime); + U.putOrderedObject(w, QPARKER, null); + U.putObject(wt, PARKBLOCKER, null); + if (w.scanState >= 0) + break; + if (parkTime != 0L && ctl == c && + deadline - System.nanoTime() <= 0L && + U.compareAndSwapLong(this, CTL, c, prevctl)) + return false; // shrink pool + } + } + return true; + } + + // Joining tasks + + /** + * Tries to steal and run tasks within the target's computation. + * Uses a variant of the top-level algorithm, restricted to tasks + * with the given task as ancestor: It prefers taking and running + * eligible tasks popped from the worker's own queue (via + * popCC). Otherwise it scans others, randomly moving on + * contention or execution, deciding to give up based on a + * checksum (via return codes frob pollAndExecCC). The maxTasks + * argument supports external usages; internal calls use zero, + * allowing unbounded steps (external calls trap non-positive + * values). + * + * @param w caller + * @param maxTasks if non-zero, the maximum number of other tasks to run + * @return task status on exit + */ + final int helpComplete(WorkQueue w, CountedCompleter task, + int maxTasks) { + WorkQueue[] ws; int s = 0, m; + if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && + task != null && w != null) { + int mode = w.config; // for popCC + int r = w.hint ^ w.top; // arbitrary seed for origin + int origin = r & m; // first queue to scan + int h = 1; // 1:ran, >1:contended, <0:hash + for (int k = origin, oldSum = 0, checkSum = 0;;) { + CountedCompleter p; WorkQueue q; + if ((s = task.status) < 0) + break; + if (h == 1 && (p = w.popCC(task, mode)) != null) { + p.doExec(); // run local task + if (maxTasks != 0 && --maxTasks == 0) + break; + origin = k; // reset + oldSum = checkSum = 0; + } + else { // poll other queues + if ((q = ws[k]) == null) + h = 0; + else if ((h = q.pollAndExecCC(task)) < 0) + checkSum += h; + if (h > 0) { + if (h == 1 && maxTasks != 0 && --maxTasks == 0) + break; + r ^= r << 13; r ^= r >>> 17; r ^= r << 5; // xorshift + origin = k = r & m; // move and restart + oldSum = checkSum = 0; + } + else if ((k = (k + 1) & m) == origin) { + if (oldSum == (oldSum = checkSum)) + break; + checkSum = 0; + } } } } - return stat; - } - - /** - * Possibly releases (signals) a worker. Called only from scan() - * when a worker with apparently inactive status finds a non-empty - * queue. This requires revalidating all of the associated state - * from caller. - */ - private final void helpRelease(long c, WorkQueue[] ws, WorkQueue w, - WorkQueue q, int b) { - WorkQueue v; int e, i; Thread p; - if (w != null && w.eventCount < 0 && (e = (int)c) > 0 && - ws != null && ws.length > (i = e & SMASK) && - (v = ws[i]) != null && ctl == c) { - long nc = (((long)(v.nextWait & E_MASK)) | - ((long)((int)(c >>> 32) + UAC_UNIT)) << 32); - int ne = (e + E_SEQ) & E_MASK; - if (q != null && q.base == b && w.eventCount < 0 && - v.eventCount == (e | INT_SIGN) && - U.compareAndSwapLong(this, CTL, c, nc)) { - v.eventCount = ne; - if ((p = v.parker) != null) - U.unpark(p); - } - } + return s; } /** @@ -1799,268 +1906,167 @@ public class ForkJoinPool extends AbstractExecutorService { * execute tasks from. The first call to this method upon a * waiting join will often entail scanning/search, (which is OK * because the joiner has nothing better to do), but this method - * leaves hints in workers to speed up subsequent calls. The - * implementation is very branchy to cope with potential - * inconsistencies or loops encountering chains that are stale, - * unknown, or so long that they are likely cyclic. + * leaves hints in workers to speed up subsequent calls. * - * @param joiner the joining worker + * @param w caller * @param task the task to join - * @return 0 if no progress can be made, negative if task - * known complete, else positive */ - private int tryHelpStealer(WorkQueue joiner, ForkJoinTask task) { - int stat = 0, steps = 0; // bound to avoid cycles - if (task != null && joiner != null && - joiner.base - joiner.top >= 0) { // hoist checks - restart: for (;;) { - ForkJoinTask subtask = task; // current target - for (WorkQueue j = joiner, v;;) { // v is stealer of subtask - WorkQueue[] ws; int m, s, h; - if ((s = task.status) < 0) { - stat = s; - break restart; - } - if ((ws = workQueues) == null || (m = ws.length - 1) <= 0) - break restart; // shutting down - if ((v = ws[h = (j.hint | 1) & m]) == null || - v.currentSteal != subtask) { - for (int origin = h;;) { // find stealer - if (((h = (h + 2) & m) & 15) == 1 && - (subtask.status < 0 || j.currentJoin != subtask)) - continue restart; // occasional staleness check - if ((v = ws[h]) != null && - v.currentSteal == subtask) { - j.hint = h; // save hint + private void helpStealer(WorkQueue w, ForkJoinTask task) { + WorkQueue[] ws = workQueues; + int oldSum = 0, checkSum, m; + if (ws != null && (m = ws.length - 1) >= 0 && w != null && + task != null) { + do { // restart point + checkSum = 0; // for stability check + ForkJoinTask subtask; + WorkQueue j = w, v; // v is subtask stealer + descent: for (subtask = task; subtask.status >= 0; ) { + for (int h = j.hint | 1, k = 0, i; ; k += 2) { + if (k > m) // can't find stealer + break descent; + if ((v = ws[i = (h + k) & m]) != null) { + if (v.currentSteal == subtask) { + j.hint = i; break; } - if (h == origin) - break restart; // cannot find stealer + checkSum += v.base; } } - for (;;) { // help stealer or descend to its stealer + for (;;) { // help v or descend ForkJoinTask[] a; int b; - if (subtask.status < 0) // surround probes with - continue restart; // consistency checks - if ((b = v.base) - v.top < 0 && (a = v.array) != null) { - int i = (((a.length - 1) & b) << ASHIFT) + ABASE; - ForkJoinTask t = - (ForkJoinTask)U.getObjectVolatile(a, i); - if (subtask.status < 0 || j.currentJoin != subtask || - v.currentSteal != subtask) - continue restart; // stale - stat = 1; // apparent progress - if (v.base == b) { - if (t == null) - break restart; - if (U.compareAndSwapObject(a, i, t, null)) { - U.putOrderedInt(v, QBASE, b + 1); - ForkJoinTask ps = joiner.currentSteal; - int jt = joiner.top; - do { - joiner.currentSteal = t; - t.doExec(); // clear local tasks too - } while (task.status >= 0 && - joiner.top != jt && - (t = joiner.pop()) != null); - joiner.currentSteal = ps; - break restart; - } - } + checkSum += (b = v.base); + ForkJoinTask next = v.currentJoin; + if (subtask.status < 0 || j.currentJoin != subtask || + v.currentSteal != subtask) // stale + break descent; + if (b - v.top >= 0 || (a = v.array) == null) { + if ((subtask = next) == null) + break descent; + j = v; + break; } - else { // empty -- try to descend - ForkJoinTask next = v.currentJoin; - if (subtask.status < 0 || j.currentJoin != subtask || - v.currentSteal != subtask) - continue restart; // stale - else if (next == null || ++steps == MAX_HELP) - break restart; // dead-end or maybe cyclic - else { - subtask = next; - j = v; - break; + int i = (((a.length - 1) & b) << ASHIFT) + ABASE; + ForkJoinTask t = ((ForkJoinTask) + U.getObjectVolatile(a, i)); + if (v.base == b) { + if (t == null) // stale + break descent; + if (U.compareAndSwapObject(a, i, t, null)) { + v.base = b + 1; + ForkJoinTask ps = w.currentSteal; + int top = w.top; + do { + U.putOrderedObject(w, QCURRENTSTEAL, t); + t.doExec(); // clear local tasks too + } while (task.status >= 0 && + w.top != top && + (t = w.pop()) != null); + U.putOrderedObject(w, QCURRENTSTEAL, ps); + if (w.base != w.top) + return; // can't further help } } } } - } + } while (task.status >= 0 && oldSum != (oldSum = checkSum)); } - return stat; - } - - /** - * Analog of tryHelpStealer for CountedCompleters. Tries to steal - * and run tasks within the target's computation. - * - * @param task the task to join - * @param maxTasks the maximum number of other tasks to run - */ - final int helpComplete(WorkQueue joiner, CountedCompleter task, - int maxTasks) { - WorkQueue[] ws; int m; - int s = 0; - if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && - joiner != null && task != null) { - int j = joiner.poolIndex; - int scans = m + m + 1; - long c = 0L; // for stability check - for (int k = scans; ; j += 2) { - WorkQueue q; - if ((s = task.status) < 0) - break; - else if (joiner.internalPopAndExecCC(task)) { - if (--maxTasks <= 0) { - s = task.status; - break; - } - k = scans; - } - else if ((s = task.status) < 0) - break; - else if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) { - if (--maxTasks <= 0) { - s = task.status; - break; - } - k = scans; - } - else if (--k < 0) { - if (c == (c = ctl)) - break; - k = scans; - } - } - } - return s; } /** * Tries to decrement active count (sometimes implicitly) and * possibly release or create a compensating worker in preparation - * for blocking. Fails on contention or termination. Otherwise, - * adds a new thread if no idle workers are available and pool - * may become starved. + * for blocking. Returns false (retryable by caller), on + * contention, detected staleness, instability, or termination. * - * @param c the assumed ctl value + * @param w caller */ - final boolean tryCompensate(long c) { - WorkQueue[] ws = workQueues; - int pc = parallelism, e = (int)c, m, tc; - if (ws != null && (m = ws.length - 1) >= 0 && e >= 0 && ctl == c) { - WorkQueue w = ws[e & m]; - if (e != 0 && w != null) { - Thread p; - long nc = ((long)(w.nextWait & E_MASK) | - (c & (AC_MASK|TC_MASK))); - int ne = (e + E_SEQ) & E_MASK; - if (w.eventCount == (e | INT_SIGN) && - U.compareAndSwapLong(this, CTL, c, nc)) { - w.eventCount = ne; - if ((p = w.parker) != null) - U.unpark(p); - return true; // replace with idle worker + private boolean tryCompensate(WorkQueue w) { + boolean canBlock; + WorkQueue[] ws; long c; int m, pc, sp; + if (w == null || w.qlock < 0 || // caller terminating + (ws = workQueues) == null || (m = ws.length - 1) <= 0 || + (pc = config & SMASK) == 0) // parallelism disabled + canBlock = false; + else if ((sp = (int)(c = ctl)) != 0) // release idle worker + canBlock = tryRelease(c, ws[sp & m], 0L); + else { + int ac = (int)(c >> AC_SHIFT) + pc; + int tc = (short)(c >> TC_SHIFT) + pc; + int nbusy = 0; // validate saturation + for (int i = 0; i <= m; ++i) { // two passes of odd indices + WorkQueue v; + if ((v = ws[((i << 1) | 1) & m]) != null) { + if ((v.scanState & SCANNING) != 0) + break; + ++nbusy; } } - else if ((tc = (short)(c >>> TC_SHIFT)) >= 0 && - (int)(c >> AC_SHIFT) + pc > 1) { - long nc = ((c - AC_UNIT) & AC_MASK) | (c & ~AC_MASK); - if (U.compareAndSwapLong(this, CTL, c, nc)) - return true; // no compensation + if (nbusy != (tc << 1) || ctl != c) + canBlock = false; // unstable or stale + else if (tc >= pc && ac > 1 && w.isEmpty()) { + long nc = ((AC_MASK & (c - AC_UNIT)) | + (~AC_MASK & c)); // uncompensated + canBlock = U.compareAndSwapLong(this, CTL, c, nc); } - else if (tc + pc < MAX_CAP) { - long nc = ((c + TC_UNIT) & TC_MASK) | (c & ~TC_MASK); - if (U.compareAndSwapLong(this, CTL, c, nc)) { - ForkJoinWorkerThreadFactory fac; - Throwable ex = null; - ForkJoinWorkerThread wt = null; - try { - if ((fac = factory) != null && - (wt = fac.newThread(this)) != null) { - wt.start(); - return true; - } - } catch (Throwable rex) { - ex = rex; - } - deregisterWorker(wt, ex); // clean up and return false - } + else if (tc >= MAX_CAP || + (this == common && tc >= pc + commonMaxSpares)) + throw new RejectedExecutionException( + "Thread limit exceeded replacing blocked worker"); + else { // similar to tryAddWorker + boolean add = false; int rs; // CAS within lock + long nc = ((AC_MASK & c) | + (TC_MASK & (c + TC_UNIT))); + if (((rs = lockRunState()) & STOP) == 0) + add = U.compareAndSwapLong(this, CTL, c, nc); + unlockRunState(rs, rs & ~RSLOCK); + canBlock = add && createWorker(); // throws on exception } } - return false; + return canBlock; } /** - * Helps and/or blocks until the given task is done. + * Helps and/or blocks until the given task is done or timeout. * - * @param joiner the joining worker + * @param w caller * @param task the task + * @param deadline for timed waits, if nonzero * @return task status on exit */ - final int awaitJoin(WorkQueue joiner, ForkJoinTask task) { + final int awaitJoin(WorkQueue w, ForkJoinTask task, long deadline) { int s = 0; - if (task != null && (s = task.status) >= 0 && joiner != null) { - ForkJoinTask prevJoin = joiner.currentJoin; - joiner.currentJoin = task; - do {} while (joiner.tryRemoveAndExec(task) && // process local tasks - (s = task.status) >= 0); - if (s >= 0 && (task instanceof CountedCompleter)) - s = helpComplete(joiner, (CountedCompleter)task, Integer.MAX_VALUE); - long cc = 0; // for stability checks - while (s >= 0 && (s = task.status) >= 0) { - if ((s = tryHelpStealer(joiner, task)) == 0 && - (s = task.status) >= 0) { - if (!tryCompensate(cc)) - cc = ctl; - else { - if (task.trySetSignal() && (s = task.status) >= 0) { - synchronized (task) { - if (task.status >= 0) { - try { // see ForkJoinTask - task.wait(); // for explanation - } catch (InterruptedException ie) { - } - } - else - task.notifyAll(); - } - } - long c; // reactivate - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, - ((c & ~AC_MASK) | - ((c & AC_MASK) + AC_UNIT)))); - } + if (task != null && w != null) { + ForkJoinTask prevJoin = w.currentJoin; + U.putOrderedObject(w, QCURRENTJOIN, task); + CountedCompleter cc = (task instanceof CountedCompleter) ? + (CountedCompleter)task : null; + for (;;) { + if ((s = task.status) < 0) + break; + if (cc != null) + helpComplete(w, cc, 0); + else if (w.base == w.top || w.tryRemoveAndExec(task)) + helpStealer(w, task); + if ((s = task.status) < 0) + break; + long ms, ns; + if (deadline == 0L) + ms = 0L; + else if ((ns = deadline - System.nanoTime()) <= 0L) + break; + else if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) <= 0L) + ms = 1L; + if (tryCompensate(w)) { + task.internalWait(ms); + U.getAndAddLong(this, CTL, AC_UNIT); } } - joiner.currentJoin = prevJoin; + U.putOrderedObject(w, QCURRENTJOIN, prevJoin); } return s; } - /** - * Stripped-down variant of awaitJoin used by timed joins. Tries - * to help join only while there is continuous progress. (Caller - * will then enter a timed wait.) - * - * @param joiner the joining worker - * @param task the task - */ - final void helpJoinOnce(WorkQueue joiner, ForkJoinTask task) { - int s; - if (joiner != null && task != null && (s = task.status) >= 0) { - ForkJoinTask prevJoin = joiner.currentJoin; - joiner.currentJoin = task; - do {} while (joiner.tryRemoveAndExec(task) && // process local tasks - (s = task.status) >= 0); - if (s >= 0) { - if (task instanceof CountedCompleter) - helpComplete(joiner, (CountedCompleter)task, Integer.MAX_VALUE); - do {} while (task.status >= 0 && - tryHelpStealer(joiner, task) > 0); - } - joiner.currentJoin = prevJoin; - } - } + // Specialized scanning /** * Returns a (probably) non-empty steal queue, if one is found @@ -2068,19 +2074,24 @@ public class ForkJoinPool extends AbstractExecutorService { * caller if, by the time it tries to use the queue, it is empty. */ private WorkQueue findNonEmptyStealQueue() { + WorkQueue[] ws; int m; // one-shot version of scan loop int r = ThreadLocalRandom.nextSecondarySeed(); - for (;;) { - int ps = plock, m; WorkQueue[] ws; WorkQueue q; - if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) { - for (int j = (m + 1) << 2; j >= 0; --j) { - if ((q = ws[(((r - j) << 1) | 1) & m]) != null && - q.base - q.top < 0) + if ((ws = workQueues) != null && (m = ws.length - 1) >= 0) { + for (int origin = r & m, k = origin, oldSum = 0, checkSum = 0;;) { + WorkQueue q; int b; + if ((q = ws[k]) != null) { + if ((b = q.base) - q.top < 0) return q; + checkSum += b; + } + if ((k = (k + 1) & m) == origin) { + if (oldSum == (oldSum = checkSum)) + break; + checkSum = 0; } } - if (plock == ps) - return null; } + return null; } /** @@ -2090,35 +2101,34 @@ public class ForkJoinPool extends AbstractExecutorService { * find tasks either. */ final void helpQuiescePool(WorkQueue w) { - ForkJoinTask ps = w.currentSteal; + ForkJoinTask ps = w.currentSteal; // save context for (boolean active = true;;) { long c; WorkQueue q; ForkJoinTask t; int b; - while ((t = w.nextLocalTask()) != null) - t.doExec(); + w.execLocalTasks(); // run locals before each scan if ((q = findNonEmptyStealQueue()) != null) { if (!active) { // re-establish active count active = true; - do {} while (!U.compareAndSwapLong - (this, CTL, c = ctl, - ((c & ~AC_MASK) | - ((c & AC_MASK) + AC_UNIT)))); + U.getAndAddLong(this, CTL, AC_UNIT); + } + if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) { + U.putOrderedObject(w, QCURRENTSTEAL, t); + t.doExec(); + if (++w.nsteals < 0) + w.transferStealCount(this); } - if ((b = q.base) - q.top < 0 && (t = q.pollAt(b)) != null) - w.runTask(t); } else if (active) { // decrement active count without queuing - long nc = ((c = ctl) & ~AC_MASK) | ((c & AC_MASK) - AC_UNIT); - if ((int)(nc >> AC_SHIFT) + parallelism == 0) + long nc = (AC_MASK & ((c = ctl) - AC_UNIT)) | (~AC_MASK & c); + if ((int)(nc >> AC_SHIFT) + (config & SMASK) <= 0) break; // bypass decrement-then-increment if (U.compareAndSwapLong(this, CTL, c, nc)) active = false; } - else if ((int)((c = ctl) >> AC_SHIFT) + parallelism <= 0 && - U.compareAndSwapLong - (this, CTL, c, ((c & ~AC_MASK) | - ((c & AC_MASK) + AC_UNIT)))) + else if ((int)((c = ctl) >> AC_SHIFT) + (config & SMASK) <= 0 && + U.compareAndSwapLong(this, CTL, c, c + AC_UNIT)) break; } + U.putOrderedObject(w, QCURRENTSTEAL, ps); } /** @@ -2141,7 +2151,7 @@ public class ForkJoinPool extends AbstractExecutorService { /** * Returns a cheap heuristic guide for task partitioning when * programmers, frameworks, tools, or languages have little or no - * idea about task granularity. In essence by offering this + * idea about task granularity. In essence, by offering this * method, we ask users only about tradeoffs in overhead vs * expected throughput and its variance, rather than how finely to * partition tasks. @@ -2179,15 +2189,12 @@ public class ForkJoinPool extends AbstractExecutorService { * many of these by further considering the number of "idle" * threads, that are known to have zero queued tasks, so * compensate by a factor of (#idle/#active) threads. - * - * Note: The approximation of #busy workers as #active workers is - * not very good under current signalling scheme, and should be - * improved. */ static int getSurplusQueuedTaskCount() { Thread t; ForkJoinWorkerThread wt; ForkJoinPool pool; WorkQueue q; if (((t = Thread.currentThread()) instanceof ForkJoinWorkerThread)) { - int p = (pool = (wt = (ForkJoinWorkerThread)t).pool).parallelism; + int p = (pool = (wt = (ForkJoinWorkerThread)t).pool). + config & SMASK; int n = (q = wt.workQueue).top - q.base; int a = (int)(pool.ctl >> AC_SHIFT) + p; return n - (a > (p >>>= 1) ? 0 : @@ -2202,13 +2209,7 @@ public class ForkJoinPool extends AbstractExecutorService { // Termination /** - * Possibly initiates and/or completes termination. The caller - * triggering termination runs three passes through workQueues: - * (0) Setting termination status, followed by wakeups of queued - * workers; (1) cancelling all tasks; (2) interrupting lagging - * threads (likely in external tasks, but possibly also blocked in - * joins). Each pass repeats previous steps because of potential - * lagging thread creation. + * Possibly initiates and/or completes termination. * * @param now if true, unconditionally terminate, else only * if no work and no active workers @@ -2216,166 +2217,256 @@ public class ForkJoinPool extends AbstractExecutorService { * @return true if now terminating or terminated */ private boolean tryTerminate(boolean now, boolean enable) { - int ps; - if (this == common) // cannot shut down + int rs; + if (this == common) // cannot shut down return false; - if ((ps = plock) >= 0) { // enable by setting plock + if ((rs = runState) >= 0) { if (!enable) return false; - if ((ps & PL_LOCK) != 0 || - !U.compareAndSwapInt(this, PLOCK, ps, ps += PL_LOCK)) - ps = acquirePlock(); - int nps = ((ps + PL_LOCK) & ~SHUTDOWN) | SHUTDOWN; - if (!U.compareAndSwapInt(this, PLOCK, ps, nps)) - releasePlock(nps); + rs = lockRunState(); // enter SHUTDOWN phase + unlockRunState(rs, (rs & ~RSLOCK) | SHUTDOWN); } - for (long c;;) { - if (((c = ctl) & STOP_BIT) != 0) { // already terminating - if ((short)(c >>> TC_SHIFT) + parallelism <= 0) { - synchronized (this) { - notifyAll(); // signal when 0 workers - } - } - return true; - } - if (!now) { // check if idle & no tasks - WorkQueue[] ws; WorkQueue w; - if ((int)(c >> AC_SHIFT) + parallelism > 0) - return false; - if ((ws = workQueues) != null) { - for (int i = 0; i < ws.length; ++i) { - if ((w = ws[i]) != null && - (!w.isEmpty() || - ((i & 1) != 0 && w.eventCount >= 0))) { - signalWork(ws, w); - return false; + + if ((rs & STOP) == 0) { + if (!now) { // check quiescence + for (long oldSum = 0L;;) { // repeat until stable + WorkQueue[] ws; WorkQueue w; int m, b; long c; + long checkSum = ctl; + if ((int)(checkSum >> AC_SHIFT) + (config & SMASK) > 0) + return false; // still active workers + if ((ws = workQueues) == null || (m = ws.length - 1) <= 0) + break; // check queues + for (int i = 0; i <= m; ++i) { + if ((w = ws[i]) != null) { + if ((b = w.base) != w.top || w.scanState >= 0 || + w.currentSteal != null) { + tryRelease(c = ctl, ws[m & (int)c], AC_UNIT); + return false; // arrange for recheck + } + checkSum += b; + if ((i & 1) == 0) + w.qlock = -1; // try to disable external } } + if (oldSum == (oldSum = checkSum)) + break; } } - if (U.compareAndSwapLong(this, CTL, c, c | STOP_BIT)) { - for (int pass = 0; pass < 3; ++pass) { - WorkQueue[] ws; WorkQueue w; Thread wt; - if ((ws = workQueues) != null) { - int n = ws.length; - for (int i = 0; i < n; ++i) { - if ((w = ws[i]) != null) { - w.qlock = -1; - if (pass > 0) { - w.cancelAll(); - if (pass > 1 && (wt = w.owner) != null) { - if (!wt.isInterrupted()) { - try { - wt.interrupt(); - } catch (Throwable ignore) { - } - } - U.unpark(wt); - } + if ((runState & STOP) == 0) { + rs = lockRunState(); // enter STOP phase + unlockRunState(rs, (rs & ~RSLOCK) | STOP); + } + } + + int pass = 0; // 3 passes to help terminate + for (long oldSum = 0L;;) { // or until done or stable + WorkQueue[] ws; WorkQueue w; ForkJoinWorkerThread wt; int m; + long checkSum = ctl; + if ((short)(checkSum >>> TC_SHIFT) + (config & SMASK) <= 0 || + (ws = workQueues) == null || (m = ws.length - 1) <= 0) { + if ((runState & TERMINATED) == 0) { + rs = lockRunState(); // done + unlockRunState(rs, (rs & ~RSLOCK) | TERMINATED); + synchronized (this) { notifyAll(); } // for awaitTermination + } + break; + } + for (int i = 0; i <= m; ++i) { + if ((w = ws[i]) != null) { + checkSum += w.base; + w.qlock = -1; // try to disable + if (pass > 0) { + w.cancelAll(); // clear queue + if (pass > 1 && (wt = w.owner) != null) { + if (!wt.isInterrupted()) { + try { // unblock join + wt.interrupt(); + } catch (Throwable ignore) { } } - } - // Wake up workers parked on event queue - int i, e; long cc; Thread p; - while ((e = (int)(cc = ctl) & E_MASK) != 0 && - (i = e & SMASK) < n && i >= 0 && - (w = ws[i]) != null) { - long nc = ((long)(w.nextWait & E_MASK) | - ((cc + AC_UNIT) & AC_MASK) | - (cc & (TC_MASK|STOP_BIT))); - if (w.eventCount == (e | INT_SIGN) && - U.compareAndSwapLong(this, CTL, cc, nc)) { - w.eventCount = (e + E_SEQ) & E_MASK; - w.qlock = -1; - if ((p = w.parker) != null) - U.unpark(p); - } + if (w.scanState < 0) + U.unpark(wt); // wake up } } } } + if (checkSum != oldSum) { // unstable + oldSum = checkSum; + pass = 0; + } + else if (pass > 3 && pass > m) // can't further help + break; + else if (++pass > 1) { // try to dequeue + long c; int j = 0, sp; // bound attempts + while (j++ <= m && (sp = (int)(c = ctl)) != 0) + tryRelease(c, ws[sp & m], AC_UNIT); + } + } + return true; + } + + // External operations + + /** + * Full version of externalPush, handling uncommon cases, as well + * as performing secondary initialization upon the first + * submission of the first task to the pool. It also detects + * first submission by an external thread and creates a new shared + * queue if the one at index if empty or contended. + * + * @param task the task. Caller must ensure non-null. + */ + private void externalSubmit(ForkJoinTask task) { + int r; // initialize caller's probe + if ((r = ThreadLocalRandom.getProbe()) == 0) { + ThreadLocalRandom.localInit(); + r = ThreadLocalRandom.getProbe(); + } + for (;;) { + WorkQueue[] ws; WorkQueue q; int rs, m, k; + boolean move = false; + if ((rs = runState) < 0) { + tryTerminate(false, false); // help terminate + throw new RejectedExecutionException(); + } + else if ((rs & STARTED) == 0 || // initialize + ((ws = workQueues) == null || (m = ws.length - 1) < 0)) { + int ns = 0; + rs = lockRunState(); + try { + if ((rs & STARTED) == 0) { + U.compareAndSwapObject(this, STEALCOUNTER, null, + new AtomicLong()); + // create workQueues array with size a power of two + int p = config & SMASK; // ensure at least 2 slots + int n = (p > 1) ? p - 1 : 1; + n |= n >>> 1; n |= n >>> 2; n |= n >>> 4; + n |= n >>> 8; n |= n >>> 16; n = (n + 1) << 1; + workQueues = new WorkQueue[n]; + ns = STARTED; + } + } finally { + unlockRunState(rs, (rs & ~RSLOCK) | ns); + } + } + else if ((q = ws[k = r & m & SQMASK]) != null) { + if (q.qlock == 0 && U.compareAndSwapInt(q, QLOCK, 0, 1)) { + ForkJoinTask[] a = q.array; + int s = q.top; + boolean submitted = false; // initial submission or resizing + try { // locked version of push + if ((a != null && a.length > s + 1 - q.base) || + (a = q.growArray()) != null) { + int j = (((a.length - 1) & s) << ASHIFT) + ABASE; + U.putOrderedObject(a, j, task); + U.putOrderedInt(q, QTOP, s + 1); + submitted = true; + } + } finally { + U.compareAndSwapInt(q, QLOCK, 1, 0); + } + if (submitted) { + signalWork(ws, q); + return; + } + } + move = true; // move on failure + } + else if (((rs = runState) & RSLOCK) == 0) { // create new queue + q = new WorkQueue(this, null); + q.hint = r; + q.config = k | SHARED_QUEUE; + q.scanState = INACTIVE; + rs = lockRunState(); // publish index + if (rs > 0 && (ws = workQueues) != null && + k < ws.length && ws[k] == null) + ws[k] = q; // else terminated + unlockRunState(rs, rs & ~RSLOCK); + } + else + move = true; // move if busy + if (move) + r = ThreadLocalRandom.advanceProbe(r); } } - // external operations on common pool + /** + * Tries to add the given task to a submission queue at + * submitter's current queue. Only the (vastly) most common path + * is directly handled in this method, while screening for need + * for externalSubmit. + * + * @param task the task. Caller must ensure non-null. + */ + final void externalPush(ForkJoinTask task) { + WorkQueue[] ws; WorkQueue q; int m; + int r = ThreadLocalRandom.getProbe(); + int rs = runState; + if ((ws = workQueues) != null && (m = (ws.length - 1)) >= 0 && + (q = ws[m & r & SQMASK]) != null && r != 0 && rs > 0 && + U.compareAndSwapInt(q, QLOCK, 0, 1)) { + ForkJoinTask[] a; int am, n, s; + if ((a = q.array) != null && + (am = a.length - 1) > (n = (s = q.top) - q.base)) { + int j = ((am & s) << ASHIFT) + ABASE; + U.putOrderedObject(a, j, task); + U.putOrderedInt(q, QTOP, s + 1); + U.putOrderedInt(q, QLOCK, 0); + if (n <= 1) + signalWork(ws, q); + return; + } + U.compareAndSwapInt(q, QLOCK, 1, 0); + } + externalSubmit(task); + } /** - * Returns common pool queue for a thread that has submitted at - * least one task. + * Returns common pool queue for an external thread. */ static WorkQueue commonSubmitterQueue() { - ForkJoinPool p; WorkQueue[] ws; int m, z; - return ((z = ThreadLocalRandom.getProbe()) != 0 && - (p = common) != null && - (ws = p.workQueues) != null && + ForkJoinPool p = common; + int r = ThreadLocalRandom.getProbe(); + WorkQueue[] ws; int m; + return (p != null && (ws = p.workQueues) != null && (m = ws.length - 1) >= 0) ? - ws[m & z & SQMASK] : null; + ws[m & r & SQMASK] : null; } /** - * Tries to pop the given task from submitter's queue in common pool. + * Performs tryUnpush for an external submitter: Finds queue, + * locks if apparently non-empty, validates upon locking, and + * adjusts top. Each check can fail but rarely does. */ final boolean tryExternalUnpush(ForkJoinTask task) { - WorkQueue joiner; ForkJoinTask[] a; int m, s; - WorkQueue[] ws = workQueues; - int z = ThreadLocalRandom.getProbe(); - boolean popped = false; - if (ws != null && (m = ws.length - 1) >= 0 && - (joiner = ws[z & m & SQMASK]) != null && - joiner.base != (s = joiner.top) && - (a = joiner.array) != null) { + WorkQueue[] ws; WorkQueue w; ForkJoinTask[] a; int m, s; + int r = ThreadLocalRandom.getProbe(); + if ((ws = workQueues) != null && (m = ws.length - 1) >= 0 && + (w = ws[m & r & SQMASK]) != null && + (a = w.array) != null && (s = w.top) != w.base) { long j = (((a.length - 1) & (s - 1)) << ASHIFT) + ABASE; - if (U.getObject(a, j) == task && - U.compareAndSwapInt(joiner, QLOCK, 0, 1)) { - if (joiner.top == s && joiner.array == a && + if (U.compareAndSwapInt(w, QLOCK, 0, 1)) { + if (w.top == s && w.array == a && + U.getObject(a, j) == task && U.compareAndSwapObject(a, j, task, null)) { - joiner.top = s - 1; - popped = true; + U.putOrderedInt(w, QTOP, s - 1); + U.putOrderedInt(w, QLOCK, 0); + return true; } - joiner.qlock = 0; + U.compareAndSwapInt(w, QLOCK, 1, 0); } } - return popped; + return false; } + /** + * Performs helpComplete for an external submitter. + */ final int externalHelpComplete(CountedCompleter task, int maxTasks) { - WorkQueue joiner; int m; - WorkQueue[] ws = workQueues; - int j = ThreadLocalRandom.getProbe(); - int s = 0; - if (ws != null && (m = ws.length - 1) >= 0 && - (joiner = ws[j & m & SQMASK]) != null && task != null) { - int scans = m + m + 1; - long c = 0L; // for stability check - j |= 1; // poll odd queues - for (int k = scans; ; j += 2) { - WorkQueue q; - if ((s = task.status) < 0) - break; - else if (joiner.externalPopAndExecCC(task)) { - if (--maxTasks <= 0) { - s = task.status; - break; - } - k = scans; - } - else if ((s = task.status) < 0) - break; - else if ((q = ws[j & m]) != null && q.pollAndExecCC(task)) { - if (--maxTasks <= 0) { - s = task.status; - break; - } - k = scans; - } - else if (--k < 0) { - if (c == (c = ctl)) - break; - k = scans; - } - } - } - return s; + WorkQueue[] ws; int n; + int r = ThreadLocalRandom.getProbe(); + return ((ws = workQueues) == null || (n = ws.length) == 0) ? 0 : + helpComplete(ws[(n - 1) & r & SQMASK], task, maxTasks); } // Exported methods @@ -2447,7 +2538,7 @@ public class ForkJoinPool extends AbstractExecutorService { this(checkParallelism(parallelism), checkFactory(factory), handler, - (asyncMode ? FIFO_QUEUE : LIFO_QUEUE), + asyncMode ? FIFO_QUEUE : LIFO_QUEUE, "ForkJoinPool-" + nextPoolId() + "-worker-"); checkPermission(); } @@ -2478,8 +2569,7 @@ public class ForkJoinPool extends AbstractExecutorService { this.workerNamePrefix = workerNamePrefix; this.factory = factory; this.ueh = handler; - this.mode = (short)mode; - this.parallelism = (short)parallelism; + this.config = (parallelism & SMASK) | mode; long np = (long)(-parallelism); // offset ctl counts this.ctl = ((np << AC_SHIFT) & AC_MASK) | ((np << TC_SHIFT) & TC_MASK); } @@ -2624,7 +2714,7 @@ public class ForkJoinPool extends AbstractExecutorService { // In previous versions of this class, this method constructed // a task to run ForkJoinTask.invokeAll, but now external // invocation of multiple tasks is at least as efficient. - ArrayList> futures = new ArrayList>(tasks.size()); + ArrayList> futures = new ArrayList<>(tasks.size()); boolean done = false; try { @@ -2670,7 +2760,7 @@ public class ForkJoinPool extends AbstractExecutorService { */ public int getParallelism() { int par; - return ((par = parallelism) > 0) ? par : 1; + return ((par = config & SMASK) > 0) ? par : 1; } /** @@ -2692,7 +2782,7 @@ public class ForkJoinPool extends AbstractExecutorService { * @return the number of worker threads */ public int getPoolSize() { - return parallelism + (short)(ctl >>> TC_SHIFT); + return (config & SMASK) + (short)(ctl >>> TC_SHIFT); } /** @@ -2702,7 +2792,7 @@ public class ForkJoinPool extends AbstractExecutorService { * @return {@code true} if this pool uses async mode */ public boolean getAsyncMode() { - return mode == FIFO_QUEUE; + return (config & FIFO_QUEUE) != 0; } /** @@ -2733,7 +2823,7 @@ public class ForkJoinPool extends AbstractExecutorService { * @return the number of active threads */ public int getActiveThreadCount() { - int r = parallelism + (int)(ctl >> AC_SHIFT); + int r = (config & SMASK) + (int)(ctl >> AC_SHIFT); return (r <= 0) ? 0 : r; // suppress momentarily negative values } @@ -2749,7 +2839,7 @@ public class ForkJoinPool extends AbstractExecutorService { * @return {@code true} if all threads are currently idle */ public boolean isQuiescent() { - return parallelism + (int)(ctl >> AC_SHIFT) <= 0; + return (config & SMASK) + (int)(ctl >> AC_SHIFT) <= 0; } /** @@ -2764,7 +2854,8 @@ public class ForkJoinPool extends AbstractExecutorService { * @return the number of steals */ public long getStealCount() { - long count = stealCount; + AtomicLong sc = stealCounter; + long count = (sc == null) ? 0L : sc.get(); WorkQueue[] ws; WorkQueue w; if ((ws = workQueues) != null) { for (int i = 1; i < ws.length; i += 2) { @@ -2894,7 +2985,8 @@ public class ForkJoinPool extends AbstractExecutorService { public String toString() { // Use a single pass through workQueues to collect counts long qt = 0L, qs = 0L; int rc = 0; - long st = stealCount; + AtomicLong sc = stealCounter; + long st = (sc == null) ? 0L : sc.get(); long c = ctl; WorkQueue[] ws; WorkQueue w; if ((ws = workQueues) != null) { @@ -2912,16 +3004,16 @@ public class ForkJoinPool extends AbstractExecutorService { } } } - int pc = parallelism; + int pc = (config & SMASK); int tc = pc + (short)(c >>> TC_SHIFT); int ac = pc + (int)(c >> AC_SHIFT); if (ac < 0) // ignore transient negative ac = 0; - String level; - if ((c & STOP_BIT) != 0) - level = (tc == 0) ? "Terminated" : "Terminating"; - else - level = plock < 0 ? "Shutting down" : "Running"; + int rs = runState; + String level = ((rs & TERMINATED) != 0 ? "Terminated" : + (rs & STOP) != 0 ? "Terminating" : + (rs & SHUTDOWN) != 0 ? "Shutting down" : + "Running"); return super.toString() + "[" + level + ", parallelism = " + pc + @@ -2983,9 +3075,7 @@ public class ForkJoinPool extends AbstractExecutorService { * @return {@code true} if all tasks have completed following shut down */ public boolean isTerminated() { - long c = ctl; - return ((c & STOP_BIT) != 0L && - (short)(c >>> TC_SHIFT) + parallelism <= 0); + return (runState & TERMINATED) != 0; } /** @@ -3002,9 +3092,8 @@ public class ForkJoinPool extends AbstractExecutorService { * @return {@code true} if terminating but not yet terminated */ public boolean isTerminating() { - long c = ctl; - return ((c & STOP_BIT) != 0L && - (short)(c >>> TC_SHIFT) + parallelism > 0); + int rs = runState; + return (rs & STOP) != 0 && (rs & TERMINATED) == 0; } /** @@ -3013,7 +3102,7 @@ public class ForkJoinPool extends AbstractExecutorService { * @return {@code true} if this pool has been shut down */ public boolean isShutdown() { - return plock < 0; + return (runState & SHUTDOWN) != 0; } /** @@ -3090,8 +3179,9 @@ public class ForkJoinPool extends AbstractExecutorService { } found = false; for (int j = (m + 1) << 2; j >= 0; --j) { - ForkJoinTask t; WorkQueue q; int b; - if ((q = ws[r++ & m]) != null && (b = q.base) - q.top < 0) { + ForkJoinTask t; WorkQueue q; int b, k; + if ((k = r++ & m) <= m && k >= 0 && (q = ws[k]) != null && + (b = q.base) - q.top < 0) { found = true; if ((t = q.pollAt(b)) != null) t.doExec(); @@ -3115,8 +3205,8 @@ public class ForkJoinPool extends AbstractExecutorService { * in {@link ForkJoinPool}s. * *

    A {@code ManagedBlocker} provides two methods. Method - * {@code isReleasable} must return {@code true} if blocking is - * not necessary. Method {@code block} blocks the current thread + * {@link #isReleasable} must return {@code true} if blocking is + * not necessary. Method {@link #block} blocks the current thread * if necessary (perhaps internally invoking {@code isReleasable} * before actually blocking). These actions are performed by any * thread invoking {@link ForkJoinPool#managedBlock(ManagedBlocker)}. @@ -3185,37 +3275,46 @@ public class ForkJoinPool extends AbstractExecutorService { } /** - * Blocks in accord with the given blocker. If the current thread - * is a {@link ForkJoinWorkerThread}, this method possibly - * arranges for a spare thread to be activated if necessary to - * ensure sufficient parallelism while the current thread is blocked. + * Runs the given possibly blocking task. When {@linkplain + * ForkJoinTask#inForkJoinPool() running in a ForkJoinPool}, this + * method possibly arranges for a spare thread to be activated if + * necessary to ensure sufficient parallelism while the current + * thread is blocked in {@link ManagedBlocker#block blocker.block()}. * - *

    If the caller is not a {@link ForkJoinTask}, this method is + *

    This method repeatedly calls {@code blocker.isReleasable()} and + * {@code blocker.block()} until either method returns {@code true}. + * Every call to {@code blocker.block()} is preceded by a call to + * {@code blocker.isReleasable()} that returned {@code false}. + * + *

    If not running in a ForkJoinPool, this method is * behaviorally equivalent to *

     {@code
          * while (!blocker.isReleasable())
          *   if (blocker.block())
    -     *     return;
    -     * }
    + * break;} * - * If the caller is a {@code ForkJoinTask}, then the pool may - * first be expanded to ensure parallelism, and later adjusted. + * If running in a ForkJoinPool, the pool may first be expanded to + * ensure sufficient parallelism available during the call to + * {@code blocker.block()}. * - * @param blocker the blocker - * @throws InterruptedException if blocker.block did so + * @param blocker the blocker task + * @throws InterruptedException if {@code blocker.block()} did so */ public static void managedBlock(ManagedBlocker blocker) throws InterruptedException { + ForkJoinPool p; + ForkJoinWorkerThread wt; Thread t = Thread.currentThread(); - if (t instanceof ForkJoinWorkerThread) { - ForkJoinPool p = ((ForkJoinWorkerThread)t).pool; + if ((t instanceof ForkJoinWorkerThread) && + (p = (wt = (ForkJoinWorkerThread)t).pool) != null) { + WorkQueue w = wt.workQueue; while (!blocker.isReleasable()) { - if (p.tryCompensate(p.ctl)) { + if (p.tryCompensate(w)) { try { do {} while (!blocker.isReleasable() && !blocker.block()); } finally { - p.incrementActiveCount(); + U.getAndAddLong(p, CTL, AC_UNIT); } break; } @@ -3241,15 +3340,18 @@ public class ForkJoinPool extends AbstractExecutorService { // Unsafe mechanics private static final sun.misc.Unsafe U; + private static final int ABASE; + private static final int ASHIFT; private static final long CTL; + private static final long RUNSTATE; + private static final long STEALCOUNTER; private static final long PARKBLOCKER; - private static final int ABASE; - private static final int ASHIFT; - private static final long STEALCOUNT; - private static final long PLOCK; - private static final long INDEXSEED; - private static final long QBASE; + private static final long QTOP; private static final long QLOCK; + private static final long QSCANSTATE; + private static final long QPARKER; + private static final long QCURRENTSTEAL; + private static final long QCURRENTJOIN; static { // initialize field offsets for CAS etc @@ -3258,20 +3360,26 @@ public class ForkJoinPool extends AbstractExecutorService { Class k = ForkJoinPool.class; CTL = U.objectFieldOffset (k.getDeclaredField("ctl")); - STEALCOUNT = U.objectFieldOffset - (k.getDeclaredField("stealCount")); - PLOCK = U.objectFieldOffset - (k.getDeclaredField("plock")); - INDEXSEED = U.objectFieldOffset - (k.getDeclaredField("indexSeed")); + RUNSTATE = U.objectFieldOffset + (k.getDeclaredField("runState")); + STEALCOUNTER = U.objectFieldOffset + (k.getDeclaredField("stealCounter")); Class tk = Thread.class; PARKBLOCKER = U.objectFieldOffset (tk.getDeclaredField("parkBlocker")); Class wk = WorkQueue.class; - QBASE = U.objectFieldOffset - (wk.getDeclaredField("base")); + QTOP = U.objectFieldOffset + (wk.getDeclaredField("top")); QLOCK = U.objectFieldOffset (wk.getDeclaredField("qlock")); + QSCANSTATE = U.objectFieldOffset + (wk.getDeclaredField("scanState")); + QPARKER = U.objectFieldOffset + (wk.getDeclaredField("parker")); + QCURRENTSTEAL = U.objectFieldOffset + (wk.getDeclaredField("currentSteal")); + QCURRENTJOIN = U.objectFieldOffset + (wk.getDeclaredField("currentJoin")); Class ak = ForkJoinTask[].class; ABASE = U.arrayBaseOffset(ak); int scale = U.arrayIndexScale(ak); @@ -3282,6 +3390,7 @@ public class ForkJoinPool extends AbstractExecutorService { throw new Error(e); } + commonMaxSpares = DEFAULT_COMMON_MAX_SPARES; defaultForkJoinWorkerThreadFactory = new DefaultForkJoinWorkerThreadFactory(); modifyThreadPermission = new RuntimePermission("modifyThread"); @@ -3289,7 +3398,7 @@ public class ForkJoinPool extends AbstractExecutorService { common = java.security.AccessController.doPrivileged (new java.security.PrivilegedAction() { public ForkJoinPool run() { return makeCommonPool(); }}); - int par = common.parallelism; // report 1 even if threads disabled + int par = common.config & SMASK; // report 1 even if threads disabled commonParallelism = par > 0 ? par : 1; } @@ -3308,6 +3417,8 @@ public class ForkJoinPool extends AbstractExecutorService { ("java.util.concurrent.ForkJoinPool.common.threadFactory"); String hp = System.getProperty ("java.util.concurrent.ForkJoinPool.common.exceptionHandler"); + String mp = System.getProperty + ("java.util.concurrent.ForkJoinPool.common.maximumSpares"); if (pp != null) parallelism = Integer.parseInt(pp); if (fp != null) @@ -3316,6 +3427,8 @@ public class ForkJoinPool extends AbstractExecutorService { if (hp != null) handler = ((UncaughtExceptionHandler)ClassLoader. getSystemClassLoader().loadClass(hp).newInstance()); + if (mp != null) + commonMaxSpares = Integer.parseInt(mp); } catch (Exception ignore) { } if (factory == null) { diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java index 936bfc23a33..4439c2407da 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinTask.java @@ -297,15 +297,22 @@ public abstract class ForkJoinTask implements Future, Serializable { } /** - * Tries to set SIGNAL status unless already completed. Used by - * ForkJoinPool. Other variants are directly incorporated into - * externalAwaitDone etc. + * If not done, sets SIGNAL status and performs Object.wait(timeout). + * This task may or may not be done on exit. Ignores interrupts. * - * @return true if successful + * @param timeout using Object.wait conventions. */ - final boolean trySetSignal() { - int s = status; - return s >= 0 && U.compareAndSwapInt(this, STATUS, s, s | SIGNAL); + final void internalWait(long timeout) { + int s; + if ((s = status) >= 0 && // force completer to issue notify + U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { + synchronized (this) { + if (status >= 0) + try { wait(timeout); } catch (InterruptedException ie) { } + else + notifyAll(); + } + } } /** @@ -313,35 +320,29 @@ public abstract class ForkJoinTask implements Future, Serializable { * @return status upon completion */ private int externalAwaitDone() { - int s; - ForkJoinPool cp = ForkJoinPool.common; - if ((s = status) >= 0) { - if (cp != null) { - if (this instanceof CountedCompleter) - s = cp.externalHelpComplete((CountedCompleter)this, Integer.MAX_VALUE); - else if (cp.tryExternalUnpush(this)) - s = doExec(); - } - if (s >= 0 && (s = status) >= 0) { - boolean interrupted = false; - do { - if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { - synchronized (this) { - if (status >= 0) { - try { - wait(); - } catch (InterruptedException ie) { - interrupted = true; - } + int s = ((this instanceof CountedCompleter) ? // try helping + ForkJoinPool.common.externalHelpComplete( + (CountedCompleter)this, 0) : + ForkJoinPool.common.tryExternalUnpush(this) ? doExec() : 0); + if (s >= 0 && (s = status) >= 0) { + boolean interrupted = false; + do { + if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { + synchronized (this) { + if (status >= 0) { + try { + wait(0L); + } catch (InterruptedException ie) { + interrupted = true; } - else - notifyAll(); } + else + notifyAll(); } - } while ((s = status) >= 0); - if (interrupted) - Thread.currentThread().interrupt(); - } + } + } while ((s = status) >= 0); + if (interrupted) + Thread.currentThread().interrupt(); } return s; } @@ -351,22 +352,22 @@ public abstract class ForkJoinTask implements Future, Serializable { */ private int externalInterruptibleAwaitDone() throws InterruptedException { int s; - ForkJoinPool cp = ForkJoinPool.common; if (Thread.interrupted()) throw new InterruptedException(); - if ((s = status) >= 0 && cp != null) { - if (this instanceof CountedCompleter) - cp.externalHelpComplete((CountedCompleter)this, Integer.MAX_VALUE); - else if (cp.tryExternalUnpush(this)) - doExec(); - } - while ((s = status) >= 0) { - if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { - synchronized (this) { - if (status >= 0) - wait(); - else - notifyAll(); + if ((s = status) >= 0 && + (s = ((this instanceof CountedCompleter) ? + ForkJoinPool.common.externalHelpComplete( + (CountedCompleter)this, 0) : + ForkJoinPool.common.tryExternalUnpush(this) ? doExec() : + 0)) >= 0) { + while ((s = status) >= 0) { + if (U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { + synchronized (this) { + if (status >= 0) + wait(0L); + else + notifyAll(); + } } } } @@ -386,7 +387,7 @@ public abstract class ForkJoinTask implements Future, Serializable { ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? (w = (wt = (ForkJoinWorkerThread)t).workQueue). tryUnpush(this) && (s = doExec()) < 0 ? s : - wt.pool.awaitJoin(w, this) : + wt.pool.awaitJoin(w, this, 0L) : externalAwaitDone(); } @@ -399,7 +400,8 @@ public abstract class ForkJoinTask implements Future, Serializable { int s; Thread t; ForkJoinWorkerThread wt; return (s = doExec()) < 0 ? s : ((t = Thread.currentThread()) instanceof ForkJoinWorkerThread) ? - (wt = (ForkJoinWorkerThread)t).pool.awaitJoin(wt.workQueue, this) : + (wt = (ForkJoinWorkerThread)t).pool. + awaitJoin(wt.workQueue, this, 0L) : externalAwaitDone(); } @@ -577,7 +579,7 @@ public abstract class ForkJoinTask implements Future, Serializable { Throwable ex; if (e == null || (ex = e.ex) == null) return null; - if (false && e.thrower != Thread.currentThread().getId()) { + if (e.thrower != Thread.currentThread().getId()) { Class ec = ex.getClass(); try { Constructor noArgCtor = null; @@ -587,13 +589,17 @@ public abstract class ForkJoinTask implements Future, Serializable { Class[] ps = c.getParameterTypes(); if (ps.length == 0) noArgCtor = c; - else if (ps.length == 1 && ps[0] == Throwable.class) - return (Throwable)(c.newInstance(ex)); + else if (ps.length == 1 && ps[0] == Throwable.class) { + Throwable wx = (Throwable)c.newInstance(ex); + return (wx == null) ? ex : wx; + } } if (noArgCtor != null) { Throwable wx = (Throwable)(noArgCtor.newInstance()); - wx.initCause(ex); - return wx; + if (wx != null) { + wx.initCause(ex); + return wx; + } } } catch (Exception ignore) { } @@ -1017,67 +1023,40 @@ public abstract class ForkJoinTask implements Future, Serializable { */ public final V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { + int s; + long nanos = unit.toNanos(timeout); if (Thread.interrupted()) throw new InterruptedException(); - // Messy in part because we measure in nanosecs, but wait in millisecs - int s; long ms; - long ns = unit.toNanos(timeout); - ForkJoinPool cp; - if ((s = status) >= 0 && ns > 0L) { - long deadline = System.nanoTime() + ns; - ForkJoinPool p = null; - ForkJoinPool.WorkQueue w = null; + if ((s = status) >= 0 && nanos > 0L) { + long d = System.nanoTime() + nanos; + long deadline = (d == 0L) ? 1L : d; // avoid 0 Thread t = Thread.currentThread(); if (t instanceof ForkJoinWorkerThread) { ForkJoinWorkerThread wt = (ForkJoinWorkerThread)t; - p = wt.pool; - w = wt.workQueue; - p.helpJoinOnce(w, this); // no retries on failure + s = wt.pool.awaitJoin(wt.workQueue, this, deadline); } - else if ((cp = ForkJoinPool.common) != null) { - if (this instanceof CountedCompleter) - cp.externalHelpComplete((CountedCompleter)this, Integer.MAX_VALUE); - else if (cp.tryExternalUnpush(this)) - doExec(); - } - boolean canBlock = false; - boolean interrupted = false; - try { - while ((s = status) >= 0) { - if (w != null && w.qlock < 0) - cancelIgnoringExceptions(this); - else if (!canBlock) { - if (p == null || p.tryCompensate(p.ctl)) - canBlock = true; - } - else { - if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L && - U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { - synchronized (this) { - if (status >= 0) { - try { - wait(ms); - } catch (InterruptedException ie) { - if (p == null) - interrupted = true; - } - } - else - notifyAll(); - } + else if ((s = ((this instanceof CountedCompleter) ? + ForkJoinPool.common.externalHelpComplete( + (CountedCompleter)this, 0) : + ForkJoinPool.common.tryExternalUnpush(this) ? + doExec() : 0)) >= 0) { + long ns, ms; // measure in nanosecs, but wait in millisecs + while ((s = status) >= 0 && + (ns = deadline - System.nanoTime()) > 0L) { + if ((ms = TimeUnit.NANOSECONDS.toMillis(ns)) > 0L && + U.compareAndSwapInt(this, STATUS, s, s | SIGNAL)) { + synchronized (this) { + if (status >= 0) + wait(ms); // OK to throw InterruptedException + else + notifyAll(); } - if ((s = status) < 0 || interrupted || - (ns = deadline - System.nanoTime()) <= 0L) - break; } } - } finally { - if (p != null && canBlock) - p.incrementActiveCount(); } - if (interrupted) - throw new InterruptedException(); } + if (s >= 0) + s = status; if ((s &= DONE_MASK) != NORMAL) { Throwable ex; if (s == CANCELLED) diff --git a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java index 404c47cc01a..8723f0aac69 100644 --- a/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java +++ b/jdk/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java @@ -66,7 +66,7 @@ public class ForkJoinWorkerThread extends Thread { * owning thread. * * Support for (non-public) subclass InnocuousForkJoinWorkerThread - * requires that we break quite a lot of encapulation (via Unsafe) + * requires that we break quite a lot of encapsulation (via Unsafe) * both here and in the subclass to access and set Thread fields. */ @@ -118,7 +118,7 @@ public class ForkJoinWorkerThread extends Thread { * @return the index number */ public int getPoolIndex() { - return workQueue.poolIndex >>> 1; // ignore odd/even tag bit + return workQueue.getPoolIndex(); } /** @@ -171,7 +171,7 @@ public class ForkJoinWorkerThread extends Thread { } /** - * Erases ThreadLocals by nulling out Thread maps + * Erases ThreadLocals by nulling out Thread maps. */ final void eraseThreadLocals() { U.putObject(this, THREADLOCALS, null); @@ -246,8 +246,8 @@ public class ForkJoinWorkerThread extends Thread { /** * Returns a new group with the system ThreadGroup (the - * topmost, parentless group) as parent. Uses Unsafe to - * traverse Thread group and ThreadGroup parent fields. + * topmost, parent-less group) as parent. Uses Unsafe to + * traverse Thread.group and ThreadGroup.parent fields. */ private static ThreadGroup createThreadGroup() { try { @@ -274,4 +274,3 @@ public class ForkJoinWorkerThread extends Thread { } } - diff --git a/jdk/src/java.base/share/classes/javax/security/auth/Subject.java b/jdk/src/java.base/share/classes/javax/security/auth/Subject.java index e8ce12c9eee..0eee83c6083 100644 --- a/jdk/src/java.base/share/classes/javax/security/auth/Subject.java +++ b/jdk/src/java.base/share/classes/javax/security/auth/Subject.java @@ -182,21 +182,20 @@ public final class Subject implements java.io.Serializable { * {@code AuthPermission("modifyPublicCredentials")}. * To modify the private credential Set, the caller must have * {@code AuthPermission("modifyPrivateCredentials")}. - *

    * * @param readOnly true if the {@code Subject} is to be read-only, - * and false otherwise.

    + * and false otherwise. * * @param principals the {@code Set} of Principals - * to be associated with this {@code Subject}.

    + * to be associated with this {@code Subject}. * * @param pubCredentials the {@code Set} of public credentials - * to be associated with this {@code Subject}.

    + * to be associated with this {@code Subject}. * * @param privCredentials the {@code Set} of private credentials * to be associated with this {@code Subject}. * - * @exception NullPointerException if the specified + * @throws NullPointerException if the specified * {@code principals}, {@code pubCredentials}, * or {@code privCredentials} are {@code null}, * or a null value exists within any of these three @@ -233,10 +232,11 @@ public final class Subject implements java.io.Serializable { * Also, once a {@code Subject} is read-only, * it can not be reset to being writable again. * - *

    - * - * @exception SecurityException if the caller does not have permission - * to set this {@code Subject} to be read-only. + * @throws SecurityException if a security manager is installed and the + * caller does not have an + * {@link AuthPermission#AuthPermission(String) + * AuthPermission("setReadOnly")} permission to set this + * {@code Subject} to be read-only. */ public void setReadOnly() { java.lang.SecurityManager sm = System.getSecurityManager(); @@ -250,8 +250,6 @@ public final class Subject implements java.io.Serializable { /** * Query whether this {@code Subject} is read-only. * - *

    - * * @return true if this {@code Subject} is read-only, false otherwise. */ public boolean isReadOnly() { @@ -267,8 +265,6 @@ public final class Subject implements java.io.Serializable { * In this situation, the most recent {@code Subject} associated * with the {@code AccessControlContext} is returned. * - *

    - * * @param acc the {@code AccessControlContext} from which to retrieve * the {@code Subject}. * @@ -277,10 +273,13 @@ public final class Subject implements java.io.Serializable { * if no {@code Subject} is associated * with the provided {@code AccessControlContext}. * - * @exception SecurityException if the caller does not have permission - * to get the {@code Subject}.

    + * @throws SecurityException if a security manager is installed and the + * caller does not have an + * {@link AuthPermission#AuthPermission(String) + * AuthPermission("getSubject")} permission to get the + * {@code Subject}. * - * @exception NullPointerException if the provided + * @throws NullPointerException if the provided * {@code AccessControlContext} is {@code null}. */ public static Subject getSubject(final AccessControlContext acc) { @@ -321,26 +320,27 @@ public final class Subject implements java.io.Serializable { * passing it the provided {@code PrivilegedAction}, * as well as the newly constructed {@code AccessControlContext}. * - *

    - * * @param subject the {@code Subject} that the specified * {@code action} will run as. This parameter - * may be {@code null}.

    + * may be {@code null}. * * @param the type of the value returned by the PrivilegedAction's * {@code run} method. * * @param action the code to be run as the specified - * {@code Subject}.

    + * {@code Subject}. * * @return the value returned by the PrivilegedAction's * {@code run} method. * - * @exception NullPointerException if the {@code PrivilegedAction} - * is {@code null}.

    + * @throws NullPointerException if the {@code PrivilegedAction} + * is {@code null}. * - * @exception SecurityException if the caller does not have permission - * to invoke this method. + * @throws SecurityException if a security manager is installed and the + * caller does not have an + * {@link AuthPermission#AuthPermission(String) + * AuthPermission("doAs")} permission to invoke this + * method. */ public static T doAs(final Subject subject, final java.security.PrivilegedAction action) { @@ -377,31 +377,32 @@ public final class Subject implements java.io.Serializable { * passing it the provided {@code PrivilegedExceptionAction}, * as well as the newly constructed {@code AccessControlContext}. * - *

    - * * @param subject the {@code Subject} that the specified * {@code action} will run as. This parameter - * may be {@code null}.

    + * may be {@code null}. * * @param the type of the value returned by the * PrivilegedExceptionAction's {@code run} method. * * @param action the code to be run as the specified - * {@code Subject}.

    + * {@code Subject}. * * @return the value returned by the * PrivilegedExceptionAction's {@code run} method. * - * @exception PrivilegedActionException if the + * @throws PrivilegedActionException if the * {@code PrivilegedExceptionAction.run} - * method throws a checked exception.

    + * method throws a checked exception. * - * @exception NullPointerException if the specified + * @throws NullPointerException if the specified * {@code PrivilegedExceptionAction} is - * {@code null}.

    + * {@code null}. * - * @exception SecurityException if the caller does not have permission - * to invoke this method. + * @throws SecurityException if a security manager is installed and the + * caller does not have an + * {@link AuthPermission#AuthPermission(String) + * AuthPermission("doAs")} permission to invoke this + * method. */ public static T doAs(final Subject subject, final java.security.PrivilegedExceptionAction action) @@ -435,29 +436,30 @@ public final class Subject implements java.io.Serializable { * this method instantiates a new {@code AccessControlContext} * with an empty collection of ProtectionDomains. * - *

    - * * @param subject the {@code Subject} that the specified * {@code action} will run as. This parameter - * may be {@code null}.

    + * may be {@code null}. * * @param the type of the value returned by the PrivilegedAction's * {@code run} method. * * @param action the code to be run as the specified - * {@code Subject}.

    + * {@code Subject}. * * @param acc the {@code AccessControlContext} to be tied to the - * specified subject and action.

    + * specified subject and action. * * @return the value returned by the PrivilegedAction's * {@code run} method. * - * @exception NullPointerException if the {@code PrivilegedAction} - * is {@code null}.

    + * @throws NullPointerException if the {@code PrivilegedAction} + * is {@code null}. * - * @exception SecurityException if the caller does not have permission - * to invoke this method. + * @throws SecurityException if a security manager is installed and the + * caller does not have a + * {@link AuthPermission#AuthPermission(String) + * AuthPermission("doAsPrivileged")} permission to invoke + * this method. */ public static T doAsPrivileged(final Subject subject, final java.security.PrivilegedAction action, @@ -495,34 +497,35 @@ public final class Subject implements java.io.Serializable { * this method instantiates a new {@code AccessControlContext} * with an empty collection of ProtectionDomains. * - *

    - * * @param subject the {@code Subject} that the specified * {@code action} will run as. This parameter - * may be {@code null}.

    + * may be {@code null}. * * @param the type of the value returned by the * PrivilegedExceptionAction's {@code run} method. * * @param action the code to be run as the specified - * {@code Subject}.

    + * {@code Subject}. * * @param acc the {@code AccessControlContext} to be tied to the - * specified subject and action.

    + * specified subject and action. * * @return the value returned by the * PrivilegedExceptionAction's {@code run} method. * - * @exception PrivilegedActionException if the + * @throws PrivilegedActionException if the * {@code PrivilegedExceptionAction.run} - * method throws a checked exception.

    + * method throws a checked exception. * - * @exception NullPointerException if the specified + * @throws NullPointerException if the specified * {@code PrivilegedExceptionAction} is - * {@code null}.

    + * {@code null}. * - * @exception SecurityException if the caller does not have permission - * to invoke this method. + * @throws SecurityException if a security manager is installed and the + * caller does not have a + * {@link AuthPermission#AuthPermission(String) + * AuthPermission("doAsPrivileged")} permission to invoke + * this method. */ public static T doAsPrivileged(final Subject subject, final java.security.PrivilegedExceptionAction action, @@ -577,9 +580,12 @@ public final class Subject implements java.io.Serializable { * to the returned {@code Set} affects the internal * {@code Principal} {@code Set} as well. * - *

    + *

    If a security manager is installed, the caller must have a + * {@link AuthPermission#AuthPermission(String) + * AuthPermission("modifyPrincipals")} permission to modify + * the returned set, or a {@code SecurityException} will be thrown. * - * @return The {@code Set} of Principals associated with this + * @return the {@code Set} of Principals associated with this * {@code Subject}. */ public Set getPrincipals() { @@ -600,8 +606,6 @@ public final class Subject implements java.io.Serializable { * Modifications to the returned {@code Set} * will not affect the internal {@code Principal} {@code Set}. * - *

    - * * @param the type of the class modeled by {@code c} * * @param c the returned {@code Set} of Principals will all be @@ -610,8 +614,8 @@ public final class Subject implements java.io.Serializable { * @return a {@code Set} of Principals that are instances of the * specified {@code Class}. * - * @exception NullPointerException if the specified {@code Class} - * is {@code null}. + * @throws NullPointerException if the specified {@code Class} + * is {@code null}. */ public Set getPrincipals(Class c) { @@ -632,9 +636,12 @@ public final class Subject implements java.io.Serializable { * to the returned {@code Set} affects the internal public * Credential {@code Set} as well. * - *

    + *

    If a security manager is installed, the caller must have a + * {@link AuthPermission#AuthPermission(String) + * AuthPermission("modifyPublicCredentials")} permission to modify + * the returned set, or a {@code SecurityException} will be thrown. * - * @return A {@code Set} of public credentials held by this + * @return a {@code Set} of public credentials held by this * {@code Subject}. */ public Set getPublicCredentials() { @@ -653,20 +660,18 @@ public final class Subject implements java.io.Serializable { * to the returned {@code Set} affects the internal private * Credential {@code Set} as well. * - *

    A caller requires permissions to access the Credentials - * in the returned {@code Set}, or to modify the - * {@code Set} itself. A {@code SecurityException} - * is thrown if the caller does not have the proper permissions. + *

    If a security manager is installed, the caller must have a + * {@link AuthPermission#AuthPermission(String) + * AuthPermission("modifyPrivateCredentials")} permission to modify + * the returned set, or a {@code SecurityException} will be thrown. * *

    While iterating through the {@code Set}, - * a {@code SecurityException} is thrown - * if the caller does not have permission to access a - * particular Credential. The {@code Iterator} - * is nevertheless advanced to next element in the {@code Set}. + * a {@code SecurityException} is thrown if a security manager is installed + * and the caller does not have a {@link PrivateCredentialPermission} + * to access a particular Credential. The {@code Iterator} + * is nevertheless advanced to the next element in the {@code Set}. * - *

    - * - * @return A {@code Set} of private credentials held by this + * @return a {@code Set} of private credentials held by this * {@code Subject}. */ public Set getPrivateCredentials() { @@ -695,8 +700,6 @@ public final class Subject implements java.io.Serializable { * Modifications to the returned {@code Set} * will not affect the internal public Credential {@code Set}. * - *

    - * * @param the type of the class modeled by {@code c} * * @param c the returned {@code Set} of public credentials will all be @@ -705,7 +708,7 @@ public final class Subject implements java.io.Serializable { * @return a {@code Set} of public credentials that are instances * of the specified {@code Class}. * - * @exception NullPointerException if the specified {@code Class} + * @throws NullPointerException if the specified {@code Class} * is {@code null}. */ public Set getPublicCredentials(Class c) { @@ -723,9 +726,9 @@ public final class Subject implements java.io.Serializable { * {@code Subject} that are instances or subclasses of the specified * {@code Class}. * - *

    The caller must have permission to access all of the - * requested Credentials, or a {@code SecurityException} - * will be thrown. + *

    If a security manager is installed, the caller must have a + * {@link PrivateCredentialPermission} to access all of the requested + * Credentials, or a {@code SecurityException} will be thrown. * *

    The returned {@code Set} is not backed by this Subject's * internal private Credential {@code Set}. A new @@ -733,8 +736,6 @@ public final class Subject implements java.io.Serializable { * Modifications to the returned {@code Set} * will not affect the internal private Credential {@code Set}. * - *

    - * * @param the type of the class modeled by {@code c} * * @param c the returned {@code Set} of private credentials will all be @@ -743,7 +744,7 @@ public final class Subject implements java.io.Serializable { * @return a {@code Set} of private credentials that are instances * of the specified {@code Class}. * - * @exception NullPointerException if the specified {@code Class} + * @throws NullPointerException if the specified {@code Class} * is {@code null}. */ public Set getPrivateCredentials(Class c) { @@ -772,19 +773,18 @@ public final class Subject implements java.io.Serializable { * equal if their {@code Principal} and {@code Credential} * Sets are equal. * - *

    - * * @param o Object to be compared for equality with this * {@code Subject}. * * @return true if the specified Object is equal to this * {@code Subject}. * - * @exception SecurityException if the caller does not have permission - * to access the private credentials for this {@code Subject}, - * or if the caller does not have permission to access the - * private credentials for the provided {@code Subject}. + * @throws SecurityException if a security manager is installed and the + * caller does not have a {@link PrivateCredentialPermission} + * permission to access the private credentials for this + * {@code Subject} or the provided {@code Subject}. */ + @Override public boolean equals(Object o) { if (o == null) { @@ -834,10 +834,9 @@ public final class Subject implements java.io.Serializable { /** * Return the String representation of this {@code Subject}. * - *

    - * * @return the String representation of this {@code Subject}. */ + @Override public String toString() { return toString(true); } @@ -895,13 +894,13 @@ public final class Subject implements java.io.Serializable { /** * Returns a hashcode for this {@code Subject}. * - *

    - * * @return a hashcode for this {@code Subject}. * - * @exception SecurityException if the caller does not have permission - * to access this Subject's private credentials. + * @throws SecurityException if a security manager is installed and the + * caller does not have a {@link PrivateCredentialPermission} + * permission to access this Subject's private credentials. */ + @Override public int hashCode() { /** @@ -996,7 +995,7 @@ public final class Subject implements java.io.Serializable { * * @param coll A {@code Collection} to be tested for null references * - * @exception NullPointerException if the specified collection is either + * @throws NullPointerException if the specified collection is either * {@code null} or contains a {@code null} element */ private static void collectionNullClean(Collection coll) { @@ -1546,7 +1545,7 @@ public final class Subject implements java.io.Serializable { } } - static class AuthPermissionHolder { + static final class AuthPermissionHolder { static final AuthPermission DO_AS_PERMISSION = new AuthPermission("doAs"); diff --git a/jdk/src/java.base/share/classes/sun/invoke/util/ValueConversions.java b/jdk/src/java.base/share/classes/sun/invoke/util/ValueConversions.java index e3095fce2d7..64b52f4569a 100644 --- a/jdk/src/java.base/share/classes/sun/invoke/util/ValueConversions.java +++ b/jdk/src/java.base/share/classes/sun/invoke/util/ValueConversions.java @@ -29,38 +29,34 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodHandles.Lookup; import java.lang.invoke.MethodType; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.EnumMap; -import java.util.List; public class ValueConversions { private static final Class THIS_CLASS = ValueConversions.class; - // Do not adjust this except for special platforms: - private static final int MAX_ARITY; - static { - final Object[] values = { 255 }; - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - values[0] = Integer.getInteger(THIS_CLASS.getName()+".MAX_ARITY", 255); - return null; - } - }); - MAX_ARITY = (Integer) values[0]; - } - private static final Lookup IMPL_LOOKUP = MethodHandles.lookup(); - private static EnumMap[] newWrapperCaches(int n) { - @SuppressWarnings("unchecked") // generic array creation - EnumMap[] caches - = (EnumMap[]) new EnumMap[n]; + /** Thread-safe canonicalized mapping from Wrapper to MethodHandle + * with unsynchronized reads and synchronized writes. + * It's safe to publish MethodHandles by data race because they are immutable. */ + private static class WrapperCache { + /** EnumMap uses preconstructed array internally, which is constant during it's lifetime. */ + private final EnumMap map = new EnumMap<>(Wrapper.class); + + public MethodHandle get(Wrapper w) { + return map.get(w); + } + public synchronized MethodHandle put(final Wrapper w, final MethodHandle mh) { + // Simulate CAS to avoid racy duplication + MethodHandle prev = map.putIfAbsent(w, mh); + if (prev != null) return prev; + return mh; + } + } + + private static WrapperCache[] newWrapperCaches(int n) { + WrapperCache[] caches = new WrapperCache[n]; for (int i = 0; i < n; i++) - caches[i] = new EnumMap<>(Wrapper.class); + caches[i] = new WrapperCache(); return caches; } @@ -71,63 +67,92 @@ public class ValueConversions { // implicit conversions sanctioned by JLS 5.1.2, etc. // explicit conversions as allowed by explicitCastArguments + static int unboxInteger(Integer x) { + return x; + } static int unboxInteger(Object x, boolean cast) { if (x instanceof Integer) - return ((Integer) x).intValue(); + return (Integer) x; return primitiveConversion(Wrapper.INT, x, cast).intValue(); } + static byte unboxByte(Byte x) { + return x; + } static byte unboxByte(Object x, boolean cast) { if (x instanceof Byte) - return ((Byte) x).byteValue(); + return (Byte) x; return primitiveConversion(Wrapper.BYTE, x, cast).byteValue(); } + static short unboxShort(Short x) { + return x; + } static short unboxShort(Object x, boolean cast) { if (x instanceof Short) - return ((Short) x).shortValue(); + return (Short) x; return primitiveConversion(Wrapper.SHORT, x, cast).shortValue(); } + static boolean unboxBoolean(Boolean x) { + return x; + } static boolean unboxBoolean(Object x, boolean cast) { if (x instanceof Boolean) - return ((Boolean) x).booleanValue(); + return (Boolean) x; return (primitiveConversion(Wrapper.BOOLEAN, x, cast).intValue() & 1) != 0; } + static char unboxCharacter(Character x) { + return x; + } static char unboxCharacter(Object x, boolean cast) { if (x instanceof Character) - return ((Character) x).charValue(); + return (Character) x; return (char) primitiveConversion(Wrapper.CHAR, x, cast).intValue(); } + static long unboxLong(Long x) { + return x; + } static long unboxLong(Object x, boolean cast) { if (x instanceof Long) - return ((Long) x).longValue(); + return (Long) x; return primitiveConversion(Wrapper.LONG, x, cast).longValue(); } + static float unboxFloat(Float x) { + return x; + } static float unboxFloat(Object x, boolean cast) { if (x instanceof Float) - return ((Float) x).floatValue(); + return (Float) x; return primitiveConversion(Wrapper.FLOAT, x, cast).floatValue(); } + static double unboxDouble(Double x) { + return x; + } static double unboxDouble(Object x, boolean cast) { if (x instanceof Double) - return ((Double) x).doubleValue(); + return (Double) x; return primitiveConversion(Wrapper.DOUBLE, x, cast).doubleValue(); } - private static MethodType unboxType(Wrapper wrap) { + private static MethodType unboxType(Wrapper wrap, int kind) { + if (kind == 0) + return MethodType.methodType(wrap.primitiveType(), wrap.wrapperType()); return MethodType.methodType(wrap.primitiveType(), Object.class, boolean.class); } - private static final EnumMap[] - UNBOX_CONVERSIONS = newWrapperCaches(2); + private static final WrapperCache[] UNBOX_CONVERSIONS = newWrapperCaches(4); - private static MethodHandle unbox(Wrapper wrap, boolean cast) { - EnumMap cache = UNBOX_CONVERSIONS[(cast?1:0)]; + private static MethodHandle unbox(Wrapper wrap, int kind) { + // kind 0 -> strongly typed with NPE + // kind 1 -> strongly typed but zero for null, + // kind 2 -> asType rules: accept multiple box types but only widening conversions with NPE + // kind 3 -> explicitCastArguments rules: allow narrowing conversions, zero for null + WrapperCache cache = UNBOX_CONVERSIONS[kind]; MethodHandle mh = cache.get(wrap); if (mh != null) { return mh; @@ -135,41 +160,59 @@ public class ValueConversions { // slow path switch (wrap) { case OBJECT: - mh = IDENTITY; break; case VOID: - mh = IGNORE; break; - } - if (mh != null) { - cache.put(wrap, mh); - return mh; + throw new IllegalArgumentException("unbox "+wrap); } // look up the method String name = "unbox" + wrap.wrapperSimpleName(); - MethodType type = unboxType(wrap); + MethodType type = unboxType(wrap, kind); try { mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type); } catch (ReflectiveOperationException ex) { mh = null; } if (mh != null) { - mh = MethodHandles.insertArguments(mh, 1, cast); - cache.put(wrap, mh); - return mh; + if (kind > 0) { + boolean cast = (kind != 2); + mh = MethodHandles.insertArguments(mh, 1, cast); + } + if (kind == 1) { // casting but exact (null -> zero) + mh = mh.asType(unboxType(wrap, 0)); + } + return cache.put(wrap, mh); } throw new IllegalArgumentException("cannot find unbox adapter for " + wrap - + (cast ? " (cast)" : "")); + + (kind <= 1 ? " (exact)" : kind == 3 ? " (cast)" : "")); } + /** Return an exact unboxer for the given primitive type. */ + public static MethodHandle unboxExact(Wrapper type) { + return unbox(type, 0); + } + + /** Return an exact unboxer for the given primitive type, with optional null-to-zero conversion. + * The boolean says whether to throw an NPE on a null value (false means unbox a zero). + * The type of the unboxer is of a form like (Integer)int. + */ + public static MethodHandle unboxExact(Wrapper type, boolean throwNPE) { + return unbox(type, throwNPE ? 0 : 1); + } + + /** Return a widening unboxer for the given primitive type. + * Widen narrower primitive boxes to the given type. + * Do not narrow any primitive values or convert null to zero. + * The type of the unboxer is of a form like (Object)int. + */ + public static MethodHandle unboxWiden(Wrapper type) { + return unbox(type, 2); + } + + /** Return a casting unboxer for the given primitive type. + * Widen or narrow primitive values to the given type, or convert null to zero, as needed. + * The type of the unboxer is of a form like (Object)int. + */ public static MethodHandle unboxCast(Wrapper type) { - return unbox(type, true); - } - - public static MethodHandle unbox(Class type) { - return unbox(Wrapper.forPrimitiveType(type), false); - } - - public static MethodHandle unboxCast(Class type) { - return unbox(Wrapper.forPrimitiveType(type), true); + return unbox(type, 3); } static private final Integer ZERO_INT = 0, ONE_INT = 1; @@ -266,57 +309,26 @@ public class ValueConversions { return MethodType.methodType(boxType, wrap.primitiveType()); } - private static final EnumMap[] - BOX_CONVERSIONS = newWrapperCaches(2); + private static final WrapperCache[] BOX_CONVERSIONS = newWrapperCaches(1); - private static MethodHandle box(Wrapper wrap, boolean exact) { - EnumMap cache = BOX_CONVERSIONS[(exact?1:0)]; + public static MethodHandle boxExact(Wrapper wrap) { + WrapperCache cache = BOX_CONVERSIONS[0]; MethodHandle mh = cache.get(wrap); if (mh != null) { return mh; } - // slow path - switch (wrap) { - case OBJECT: - mh = IDENTITY; break; - case VOID: - mh = ZERO_OBJECT; - break; - } - if (mh != null) { - cache.put(wrap, mh); - return mh; - } // look up the method String name = "box" + wrap.wrapperSimpleName(); MethodType type = boxType(wrap); - if (exact) { - try { - mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type); - } catch (ReflectiveOperationException ex) { - mh = null; - } - } else { - mh = box(wrap, !exact).asType(type.erase()); + try { + mh = IMPL_LOOKUP.findStatic(THIS_CLASS, name, type); + } catch (ReflectiveOperationException ex) { + mh = null; } if (mh != null) { - cache.put(wrap, mh); - return mh; + return cache.put(wrap, mh); } - throw new IllegalArgumentException("cannot find box adapter for " - + wrap + (exact ? " (exact)" : "")); - } - - public static MethodHandle box(Class type) { - boolean exact = false; - // e.g., boxShort(short)Short if exact, - // e.g., boxShort(short)Object if !exact - return box(Wrapper.forPrimitiveType(type), exact); - } - - public static MethodHandle box(Wrapper type) { - boolean exact = false; - return box(type, exact); + throw new IllegalArgumentException("cannot find box adapter for " + wrap); } /// Constant functions @@ -348,11 +360,10 @@ public class ValueConversions { return 0; } - private static final EnumMap[] - CONSTANT_FUNCTIONS = newWrapperCaches(2); + private static final WrapperCache[] CONSTANT_FUNCTIONS = newWrapperCaches(2); public static MethodHandle zeroConstantFunction(Wrapper wrap) { - EnumMap cache = CONSTANT_FUNCTIONS[0]; + WrapperCache cache = CONSTANT_FUNCTIONS[0]; MethodHandle mh = cache.get(wrap); if (mh != null) { return mh; @@ -373,184 +384,37 @@ public class ValueConversions { break; } if (mh != null) { - cache.put(wrap, mh); - return mh; + return cache.put(wrap, mh); } // use zeroInt and cast the result if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) { mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type); - cache.put(wrap, mh); - return mh; + return cache.put(wrap, mh); } throw new IllegalArgumentException("cannot find zero constant for " + wrap); } - /// Converting references to references. - - /** - * Identity function. - * @param x an arbitrary reference value - * @return the same value x - */ - static T identity(T x) { - return x; - } - - static T[] identity(T[] x) { - return x; - } - - /** - * Identity function on ints. - * @param x an arbitrary int value - * @return the same value x - */ - static int identity(int x) { - return x; - } - - static byte identity(byte x) { - return x; - } - - static short identity(short x) { - return x; - } - - static boolean identity(boolean x) { - return x; - } - - static char identity(char x) { - return x; - } - - /** - * Identity function on longs. - * @param x an arbitrary long value - * @return the same value x - */ - static long identity(long x) { - return x; - } - - static float identity(float x) { - return x; - } - - static double identity(double x) { - return x; - } - - private static ClassCastException newClassCastException(Class t, Object obj) { - return new ClassCastException("Cannot cast " + obj.getClass().getName() + " to " + t.getName()); - } - - private static final MethodHandle IDENTITY, CAST_REFERENCE, ZERO_OBJECT, IGNORE, EMPTY, - ARRAY_IDENTITY, FILL_NEW_TYPED_ARRAY, FILL_NEW_ARRAY; + private static final MethodHandle CAST_REFERENCE, IGNORE, EMPTY; static { try { MethodType idType = MethodType.genericMethodType(1); MethodType ignoreType = idType.changeReturnType(void.class); - MethodType zeroObjectType = MethodType.genericMethodType(0); - IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", idType); CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); - ZERO_OBJECT = IMPL_LOOKUP.findStatic(THIS_CLASS, "zeroObject", zeroObjectType); IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType); EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1)); - ARRAY_IDENTITY = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", MethodType.methodType(Object[].class, Object[].class)); - FILL_NEW_ARRAY = IMPL_LOOKUP - .findStatic(THIS_CLASS, "fillNewArray", - MethodType.methodType(Object[].class, Integer.class, Object[].class)); - FILL_NEW_TYPED_ARRAY = IMPL_LOOKUP - .findStatic(THIS_CLASS, "fillNewTypedArray", - MethodType.methodType(Object[].class, Object[].class, Integer.class, Object[].class)); } catch (NoSuchMethodException | IllegalAccessException ex) { throw newInternalError("uncaught exception", ex); } } - // Varargs methods need to be in a separately initialized class, to avoid bootstrapping problems. - static class LazyStatics { - private static final MethodHandle COPY_AS_REFERENCE_ARRAY, COPY_AS_PRIMITIVE_ARRAY, MAKE_LIST; - static { - try { - //MAKE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeArray", MethodType.methodType(Object[].class, Object[].class)); - COPY_AS_REFERENCE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsReferenceArray", MethodType.methodType(Object[].class, Class.class, Object[].class)); - COPY_AS_PRIMITIVE_ARRAY = IMPL_LOOKUP.findStatic(THIS_CLASS, "copyAsPrimitiveArray", MethodType.methodType(Object.class, Wrapper.class, Object[].class)); - MAKE_LIST = IMPL_LOOKUP.findStatic(THIS_CLASS, "makeList", MethodType.methodType(List.class, Object[].class)); - } catch (ReflectiveOperationException ex) { - throw newInternalError("uncaught exception", ex); - } - } + public static MethodHandle ignore() { + return IGNORE; } - private static final EnumMap[] WRAPPER_CASTS - = newWrapperCaches(1); - - /** Return a method that casts its sole argument (an Object) to the given type - * and returns it as the given type. - */ - public static MethodHandle cast(Class type) { - return cast(type, CAST_REFERENCE); - } - public static MethodHandle cast(Class type, MethodHandle castReference) { - if (type.isPrimitive()) throw new IllegalArgumentException("cannot cast primitive type "+type); - MethodHandle mh; - Wrapper wrap = null; - EnumMap cache = null; - if (Wrapper.isWrapperType(type)) { - wrap = Wrapper.forWrapperType(type); - cache = WRAPPER_CASTS[0]; - mh = cache.get(wrap); - if (mh != null) return mh; - } - mh = MethodHandles.insertArguments(castReference, 0, type); - if (cache != null) - cache.put(wrap, mh); - return mh; - } - - public static MethodHandle identity() { - return IDENTITY; - } - - public static MethodHandle identity(Class type) { - if (!type.isPrimitive()) - // Reference identity has been moved into MethodHandles: - return MethodHandles.identity(type); - return identity(Wrapper.findPrimitiveType(type)); - } - - public static MethodHandle identity(Wrapper wrap) { - EnumMap cache = CONSTANT_FUNCTIONS[1]; - MethodHandle mh = cache.get(wrap); - if (mh != null) { - return mh; - } - // slow path - MethodType type = MethodType.methodType(wrap.primitiveType()); - if (wrap != Wrapper.VOID) - type = type.appendParameterTypes(wrap.primitiveType()); - try { - mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "identity", type); - } catch (ReflectiveOperationException ex) { - mh = null; - } - if (mh == null && wrap == Wrapper.VOID) { - mh = EMPTY; // #(){} : #()void - } - if (mh != null) { - cache.put(wrap, mh); - return mh; - } - - if (mh != null) { - cache.put(wrap, mh); - return mh; - } - throw new IllegalArgumentException("cannot find identity for " + wrap); + /** Return a method that casts its second argument (an Object) to the given type (a Class). */ + public static MethodHandle cast() { + return CAST_REFERENCE; } /// Primitive conversions. @@ -759,11 +623,10 @@ public class ValueConversions { return (x ? (byte)1 : (byte)0); } - private static final EnumMap[] - CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length); + private static final WrapperCache[] CONVERT_PRIMITIVE_FUNCTIONS = newWrapperCaches(Wrapper.values().length); public static MethodHandle convertPrimitive(Wrapper wsrc, Wrapper wdst) { - EnumMap cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()]; + WrapperCache cache = CONVERT_PRIMITIVE_FUNCTIONS[wsrc.ordinal()]; MethodHandle mh = cache.get(wdst); if (mh != null) { return mh; @@ -771,17 +634,9 @@ public class ValueConversions { // slow path Class src = wsrc.primitiveType(); Class dst = wdst.primitiveType(); - MethodType type = src == void.class ? MethodType.methodType(dst) : MethodType.methodType(dst, src); + MethodType type = MethodType.methodType(dst, src); if (wsrc == wdst) { - mh = identity(src); - } else if (wsrc == Wrapper.VOID) { - mh = zeroConstantFunction(wdst); - } else if (wdst == Wrapper.VOID) { - mh = MethodHandles.dropArguments(EMPTY, 0, src); // Defer back to MethodHandles. - } else if (wsrc == Wrapper.OBJECT) { - mh = unboxCast(dst); - } else if (wdst == Wrapper.OBJECT) { - mh = box(src); + mh = MethodHandles.identity(src); } else { assert(src.isPrimitive() && dst.isPrimitive()); try { @@ -792,8 +647,7 @@ public class ValueConversions { } if (mh != null) { assert(mh.type() == type) : mh; - cache.put(wdst, mh); - return mh; + return cache.put(wdst, mh); } throw new IllegalArgumentException("cannot find primitive conversion function for " + @@ -808,363 +662,6 @@ public class ValueConversions { return Character.toUpperCase(x.charAt(0))+x.substring(1); } - /// Collection of multiple arguments. - - public static Object convertArrayElements(Class arrayType, Object array) { - Class src = array.getClass().getComponentType(); - Class dst = arrayType.getComponentType(); - if (src == null || dst == null) throw new IllegalArgumentException("not array type"); - Wrapper sw = (src.isPrimitive() ? Wrapper.forPrimitiveType(src) : null); - Wrapper dw = (dst.isPrimitive() ? Wrapper.forPrimitiveType(dst) : null); - int length; - if (sw == null) { - Object[] a = (Object[]) array; - length = a.length; - if (dw == null) - return Arrays.copyOf(a, length, arrayType.asSubclass(Object[].class)); - Object res = dw.makeArray(length); - dw.copyArrayUnboxing(a, 0, res, 0, length); - return res; - } - length = java.lang.reflect.Array.getLength(array); - Object[] res; - if (dw == null) { - res = Arrays.copyOf(NO_ARGS_ARRAY, length, arrayType.asSubclass(Object[].class)); - } else { - res = new Object[length]; - } - sw.copyArrayBoxing(array, 0, res, 0, length); - if (dw == null) return res; - Object a = dw.makeArray(length); - dw.copyArrayUnboxing(res, 0, a, 0, length); - return a; - } - - private static MethodHandle findCollector(String name, int nargs, Class rtype, Class... ptypes) { - MethodType type = MethodType.genericMethodType(nargs) - .changeReturnType(rtype) - .insertParameterTypes(0, ptypes); - try { - return IMPL_LOOKUP.findStatic(THIS_CLASS, name, type); - } catch (ReflectiveOperationException ex) { - return null; - } - } - - private static final Object[] NO_ARGS_ARRAY = {}; - private static Object[] makeArray(Object... args) { return args; } - private static Object[] array() { return NO_ARGS_ARRAY; } - private static Object[] array(Object a0) - { return makeArray(a0); } - private static Object[] array(Object a0, Object a1) - { return makeArray(a0, a1); } - private static Object[] array(Object a0, Object a1, Object a2) - { return makeArray(a0, a1, a2); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3) - { return makeArray(a0, a1, a2, a3); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4) - { return makeArray(a0, a1, a2, a3, a4); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5) - { return makeArray(a0, a1, a2, a3, a4, a5); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6) - { return makeArray(a0, a1, a2, a3, a4, a5, a6); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7) - { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8) - { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - private static Object[] array(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8, Object a9) - { return makeArray(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - private static MethodHandle[] makeArrays() { - ArrayList mhs = new ArrayList<>(); - for (;;) { - MethodHandle mh = findCollector("array", mhs.size(), Object[].class); - if (mh == null) break; - mhs.add(mh); - } - assert(mhs.size() == 11); // current number of methods - return mhs.toArray(new MethodHandle[MAX_ARITY+1]); - } - private static final MethodHandle[] ARRAYS = makeArrays(); - - // filling versions of the above: - // using Integer len instead of int len and no varargs to avoid bootstrapping problems - private static Object[] fillNewArray(Integer len, Object[] /*not ...*/ args) { - Object[] a = new Object[len]; - fillWithArguments(a, 0, args); - return a; - } - private static Object[] fillNewTypedArray(Object[] example, Integer len, Object[] /*not ...*/ args) { - Object[] a = Arrays.copyOf(example, len); - fillWithArguments(a, 0, args); - return a; - } - private static void fillWithArguments(Object[] a, int pos, Object... args) { - System.arraycopy(args, 0, a, pos, args.length); - } - // using Integer pos instead of int pos to avoid bootstrapping problems - private static Object[] fillArray(Integer pos, Object[] a, Object a0) - { fillWithArguments(a, pos, a0); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1) - { fillWithArguments(a, pos, a0, a1); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2) - { fillWithArguments(a, pos, a0, a1, a2); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3) - { fillWithArguments(a, pos, a0, a1, a2, a3); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8); return a; } - private static Object[] fillArray(Integer pos, Object[] a, Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8, Object a9) - { fillWithArguments(a, pos, a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); return a; } - private static MethodHandle[] makeFillArrays() { - ArrayList mhs = new ArrayList<>(); - mhs.add(null); // there is no empty fill; at least a0 is required - for (;;) { - MethodHandle mh = findCollector("fillArray", mhs.size(), Object[].class, Integer.class, Object[].class); - if (mh == null) break; - mhs.add(mh); - } - assert(mhs.size() == 11); // current number of methods - return mhs.toArray(new MethodHandle[0]); - } - private static final MethodHandle[] FILL_ARRAYS = makeFillArrays(); - - private static Object[] copyAsReferenceArray(Class arrayType, Object... a) { - return Arrays.copyOf(a, a.length, arrayType); - } - private static Object copyAsPrimitiveArray(Wrapper w, Object... boxes) { - Object a = w.makeArray(boxes.length); - w.copyArrayUnboxing(boxes, 0, a, 0, boxes.length); - return a; - } - - /** Return a method handle that takes the indicated number of Object - * arguments and returns an Object array of them, as if for varargs. - */ - public static MethodHandle varargsArray(int nargs) { - MethodHandle mh = ARRAYS[nargs]; - if (mh != null) return mh; - mh = findCollector("array", nargs, Object[].class); - if (mh != null) return ARRAYS[nargs] = mh; - mh = buildVarargsArray(FILL_NEW_ARRAY, ARRAY_IDENTITY, nargs); - assert(assertCorrectArity(mh, nargs)); - return ARRAYS[nargs] = mh; - } - - private static boolean assertCorrectArity(MethodHandle mh, int arity) { - assert(mh.type().parameterCount() == arity) : "arity != "+arity+": "+mh; - return true; - } - - private static MethodHandle buildVarargsArray(MethodHandle newArray, MethodHandle finisher, int nargs) { - // Build up the result mh as a sequence of fills like this: - // finisher(fill(fill(newArrayWA(23,x1..x10),10,x11..x20),20,x21..x23)) - // The various fill(_,10*I,___*[J]) are reusable. - int leftLen = Math.min(nargs, LEFT_ARGS); // absorb some arguments immediately - int rightLen = nargs - leftLen; - MethodHandle leftCollector = newArray.bindTo(nargs); - leftCollector = leftCollector.asCollector(Object[].class, leftLen); - MethodHandle mh = finisher; - if (rightLen > 0) { - MethodHandle rightFiller = fillToRight(LEFT_ARGS + rightLen); - if (mh == ARRAY_IDENTITY) - mh = rightFiller; - else - mh = MethodHandles.collectArguments(mh, 0, rightFiller); - } - if (mh == ARRAY_IDENTITY) - mh = leftCollector; - else - mh = MethodHandles.collectArguments(mh, 0, leftCollector); - return mh; - } - - private static final int LEFT_ARGS = (FILL_ARRAYS.length - 1); - private static final MethodHandle[] FILL_ARRAY_TO_RIGHT = new MethodHandle[MAX_ARITY+1]; - /** fill_array_to_right(N).invoke(a, argL..arg[N-1]) - * fills a[L]..a[N-1] with corresponding arguments, - * and then returns a. The value L is a global constant (LEFT_ARGS). - */ - private static MethodHandle fillToRight(int nargs) { - MethodHandle filler = FILL_ARRAY_TO_RIGHT[nargs]; - if (filler != null) return filler; - filler = buildFiller(nargs); - assert(assertCorrectArity(filler, nargs - LEFT_ARGS + 1)); - return FILL_ARRAY_TO_RIGHT[nargs] = filler; - } - private static MethodHandle buildFiller(int nargs) { - if (nargs <= LEFT_ARGS) - return ARRAY_IDENTITY; // no args to fill; return the array unchanged - // we need room for both mh and a in mh.invoke(a, arg*[nargs]) - final int CHUNK = LEFT_ARGS; - int rightLen = nargs % CHUNK; - int midLen = nargs - rightLen; - if (rightLen == 0) { - midLen = nargs - (rightLen = CHUNK); - if (FILL_ARRAY_TO_RIGHT[midLen] == null) { - // build some precursors from left to right - for (int j = LEFT_ARGS % CHUNK; j < midLen; j += CHUNK) - if (j > LEFT_ARGS) fillToRight(j); - } - } - if (midLen < LEFT_ARGS) rightLen = nargs - (midLen = LEFT_ARGS); - assert(rightLen > 0); - MethodHandle midFill = fillToRight(midLen); // recursive fill - MethodHandle rightFill = FILL_ARRAYS[rightLen].bindTo(midLen); // [midLen..nargs-1] - assert(midFill.type().parameterCount() == 1 + midLen - LEFT_ARGS); - assert(rightFill.type().parameterCount() == 1 + rightLen); - - // Combine the two fills: - // right(mid(a, x10..x19), x20..x23) - // The final product will look like this: - // right(mid(newArrayLeft(24, x0..x9), x10..x19), x20..x23) - if (midLen == LEFT_ARGS) - return rightFill; - else - return MethodHandles.collectArguments(rightFill, 0, midFill); - } - - // Type-polymorphic version of varargs maker. - private static final ClassValue TYPED_COLLECTORS - = new ClassValue() { - @Override - protected MethodHandle[] computeValue(Class type) { - return new MethodHandle[256]; - } - }; - - static final int MAX_JVM_ARITY = 255; // limit imposed by the JVM - - /** Return a method handle that takes the indicated number of - * typed arguments and returns an array of them. - * The type argument is the array type. - */ - public static MethodHandle varargsArray(Class arrayType, int nargs) { - Class elemType = arrayType.getComponentType(); - if (elemType == null) throw new IllegalArgumentException("not an array: "+arrayType); - // FIXME: Need more special casing and caching here. - if (nargs >= MAX_JVM_ARITY/2 - 1) { - int slots = nargs; - final int MAX_ARRAY_SLOTS = MAX_JVM_ARITY - 1; // 1 for receiver MH - if (arrayType == double[].class || arrayType == long[].class) - slots *= 2; - if (slots > MAX_ARRAY_SLOTS) - throw new IllegalArgumentException("too many arguments: "+arrayType.getSimpleName()+", length "+nargs); - } - if (elemType == Object.class) - return varargsArray(nargs); - // other cases: primitive arrays, subtypes of Object[] - MethodHandle cache[] = TYPED_COLLECTORS.get(elemType); - MethodHandle mh = nargs < cache.length ? cache[nargs] : null; - if (mh != null) return mh; - if (elemType.isPrimitive()) { - MethodHandle builder = FILL_NEW_ARRAY; - MethodHandle producer = buildArrayProducer(arrayType); - mh = buildVarargsArray(builder, producer, nargs); - } else { - @SuppressWarnings("unchecked") - Class objArrayType = (Class) arrayType; - Object[] example = Arrays.copyOf(NO_ARGS_ARRAY, 0, objArrayType); - MethodHandle builder = FILL_NEW_TYPED_ARRAY.bindTo(example); - MethodHandle producer = ARRAY_IDENTITY; - mh = buildVarargsArray(builder, producer, nargs); - } - mh = mh.asType(MethodType.methodType(arrayType, Collections.>nCopies(nargs, elemType))); - assert(assertCorrectArity(mh, nargs)); - if (nargs < cache.length) - cache[nargs] = mh; - return mh; - } - - private static MethodHandle buildArrayProducer(Class arrayType) { - Class elemType = arrayType.getComponentType(); - if (elemType.isPrimitive()) - return LazyStatics.COPY_AS_PRIMITIVE_ARRAY.bindTo(Wrapper.forPrimitiveType(elemType)); - else - return LazyStatics.COPY_AS_REFERENCE_ARRAY.bindTo(arrayType); - } - - // List version of varargs maker. - - private static final List NO_ARGS_LIST = Arrays.asList(NO_ARGS_ARRAY); - private static List makeList(Object... args) { return Arrays.asList(args); } - private static List list() { return NO_ARGS_LIST; } - private static List list(Object a0) - { return makeList(a0); } - private static List list(Object a0, Object a1) - { return makeList(a0, a1); } - private static List list(Object a0, Object a1, Object a2) - { return makeList(a0, a1, a2); } - private static List list(Object a0, Object a1, Object a2, Object a3) - { return makeList(a0, a1, a2, a3); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4) - { return makeList(a0, a1, a2, a3, a4); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5) - { return makeList(a0, a1, a2, a3, a4, a5); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6) - { return makeList(a0, a1, a2, a3, a4, a5, a6); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7) - { return makeList(a0, a1, a2, a3, a4, a5, a6, a7); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8) - { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8); } - private static List list(Object a0, Object a1, Object a2, Object a3, - Object a4, Object a5, Object a6, Object a7, - Object a8, Object a9) - { return makeList(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9); } - private static MethodHandle[] makeLists() { - ArrayList mhs = new ArrayList<>(); - for (;;) { - MethodHandle mh = findCollector("list", mhs.size(), List.class); - if (mh == null) break; - mhs.add(mh); - } - assert(mhs.size() == 11); // current number of methods - return mhs.toArray(new MethodHandle[MAX_ARITY+1]); - } - private static final MethodHandle[] LISTS = makeLists(); - - /** Return a method handle that takes the indicated number of Object - * arguments and returns a List. - */ - public static MethodHandle varargsList(int nargs) { - MethodHandle mh = LISTS[nargs]; - if (mh != null) return mh; - mh = findCollector("list", nargs, List.class); - if (mh != null) return LISTS[nargs] = mh; - return LISTS[nargs] = buildVarargsList(nargs); - } - private static MethodHandle buildVarargsList(int nargs) { - return MethodHandles.filterReturnValue(varargsArray(nargs), LazyStatics.MAKE_LIST); - } - // handy shared exception makers (they simplify the common case code) private static InternalError newInternalError(String message, Throwable cause) { return new InternalError(message, cause); diff --git a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyType.java b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyType.java index 52b32c40e89..ce37b88c76d 100644 --- a/jdk/src/java.base/share/classes/sun/invoke/util/VerifyType.java +++ b/jdk/src/java.base/share/classes/sun/invoke/util/VerifyType.java @@ -40,18 +40,38 @@ public class VerifyType { /** * True if a value can be stacked as the source type and unstacked as the * destination type, without violating the JVM's type consistency. + *

    + * If both types are references, we apply the verifier's subclass check + * (or subtyping, if keepInterfaces). + * If the src type is a type guaranteed to be null (Void) it can be converted + * to any other reference type. + *

    + * If both types are primitives, we apply the verifier's primitive conversions. + * These do not include Java conversions such as long to double, since those + * require computation and (in general) stack depth changes. + * But very simple 32-bit viewing changes, such as byte to int, + * are null conversions, because they do not require any computation. + * These conversions are from any type to a wider type up to 32 bits, + * as long as the conversion is not signed to unsigned (byte to char). + *

    + * The primitive type 'void' does not interconvert with any other type, + * even though it is legal to drop any type from the stack and "return void". + * The stack effects, though are different between void and any other type, + * so it is safer to report a non-trivial conversion. * * @param src the type of a stacked value * @param dst the type by which we'd like to treat it + * @param keepInterfaces if false, we treat any interface as if it were Object * @return whether the retyping can be done without motion or reformatting */ - public static boolean isNullConversion(Class src, Class dst) { + public static boolean isNullConversion(Class src, Class dst, boolean keepInterfaces) { if (src == dst) return true; // Verifier allows any interface to be treated as Object: - if (dst.isInterface()) dst = Object.class; - if (src.isInterface()) src = Object.class; - if (src == dst) return true; // check again - if (dst == void.class) return true; // drop any return value + if (!keepInterfaces) { + if (dst.isInterface()) dst = Object.class; + if (src.isInterface()) src = Object.class; + if (src == dst) return true; // check again + } if (isNullType(src)) return !dst.isPrimitive(); if (!src.isPrimitive()) return dst.isAssignableFrom(src); if (!dst.isPrimitive()) return false; @@ -82,25 +102,13 @@ public class VerifyType { * Is the given type java.lang.Null or an equivalent null-only type? */ public static boolean isNullType(Class type) { - if (type == null) return false; - return type == NULL_CLASS - // This one may also be used as a null type. - // TO DO: Decide if we really want to legitimize it here. - // Probably we do, unless java.lang.Null really makes it into Java 7 - //|| type == Void.class - // Locally known null-only class: - || type == Empty.class - ; - } - private static final Class NULL_CLASS; - static { - Class nullClass = null; - try { - nullClass = Class.forName("java.lang.Null"); - } catch (ClassNotFoundException ex) { - // OK, we'll cope - } - NULL_CLASS = nullClass; + // Any reference statically typed as Void is guaranteed to be null. + // Therefore, it can be safely treated as a value of any + // other type that admits null, i.e., a reference type. + if (type == Void.class) return true; + // Locally known null-only class: + if (type == Empty.class) return true; + return false; } /** @@ -111,14 +119,14 @@ public class VerifyType { * @param recv the type of the method handle receiving the call * @return whether the retyping can be done without motion or reformatting */ - public static boolean isNullConversion(MethodType call, MethodType recv) { + public static boolean isNullConversion(MethodType call, MethodType recv, boolean keepInterfaces) { if (call == recv) return true; int len = call.parameterCount(); if (len != recv.parameterCount()) return false; for (int i = 0; i < len; i++) - if (!isNullConversion(call.parameterType(i), recv.parameterType(i))) + if (!isNullConversion(call.parameterType(i), recv.parameterType(i), keepInterfaces)) return false; - return isNullConversion(recv.returnType(), call.returnType()); + return isNullConversion(recv.returnType(), call.returnType(), keepInterfaces); } /** diff --git a/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java b/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java index 6c4be456aee..2732e28c8ed 100644 --- a/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java +++ b/jdk/src/java.base/share/classes/sun/invoke/util/Wrapper.java @@ -230,14 +230,6 @@ public enum Wrapper { */ public T zero(Class type) { return convert(zero, type); } -// /** Produce a wrapper for the given wrapper or primitive type. */ -// public static Wrapper valueOf(Class type) { -// if (isPrimitiveType(type)) -// return forPrimitiveType(type); -// else -// return forWrapperType(type); -// } - /** Return the wrapper that wraps values of the given type. * The type may be {@code Object}, meaning the {@code OBJECT} wrapper. * Otherwise, the type must be a primitive. diff --git a/jdk/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java b/jdk/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java index 31578b50d78..f20feec8ae0 100644 --- a/jdk/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java +++ b/jdk/src/java.base/share/classes/sun/net/InetAddressCachePolicy.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -56,7 +56,7 @@ public final class InetAddressCachePolicy { * caching. For security reasons, this caching is made forever when * a security manager is set. */ - private static int cachePolicy = FOREVER; + private static volatile int cachePolicy = FOREVER; /* The Java-level namelookup cache policy for negative lookups: * @@ -66,7 +66,7 @@ public final class InetAddressCachePolicy { * default value is 0. It can be set to some other value for * performance reasons. */ - private static int negativeCachePolicy = NEVER; + private static volatile int negativeCachePolicy = NEVER; /* * Whether or not the cache policy for successful lookups was set @@ -110,10 +110,7 @@ public final class InetAddressCachePolicy { }); if (tmp != null) { - cachePolicy = tmp.intValue(); - if (cachePolicy < 0) { - cachePolicy = FOREVER; - } + cachePolicy = tmp < 0 ? FOREVER : tmp; propertySet = true; } else { /* No properties defined for positive caching. If there is no @@ -148,19 +145,16 @@ public final class InetAddressCachePolicy { }); if (tmp != null) { - negativeCachePolicy = tmp.intValue(); - if (negativeCachePolicy < 0) { - negativeCachePolicy = FOREVER; - } + negativeCachePolicy = tmp < 0 ? FOREVER : tmp; propertyNegativeSet = true; } } - public static synchronized int get() { + public static int get() { return cachePolicy; } - public static synchronized int getNegative() { + public static int getNegative() { return negativeCachePolicy; } @@ -190,7 +184,7 @@ public final class InetAddressCachePolicy { * @param newPolicy the value in seconds for how long the lookup * should be cached */ - public static synchronized void setNegativeIfNotSet(int newPolicy) { + public static void setNegativeIfNotSet(int newPolicy) { /* * When setting the new value we may want to signal that the * cache should be flushed, though this doesn't seem strictly @@ -200,7 +194,8 @@ public final class InetAddressCachePolicy { // Negative caching does not seem to have any security // implications. // checkValue(newPolicy, negativeCachePolicy); - negativeCachePolicy = newPolicy; + // but we should normalize negative policy + negativeCachePolicy = newPolicy < 0 ? FOREVER : newPolicy; } } diff --git a/jdk/src/java.base/share/classes/sun/net/www/MimeEntry.java b/jdk/src/java.base/share/classes/sun/net/www/MimeEntry.java index 7a7bcce453c..f96953a42d4 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/MimeEntry.java +++ b/jdk/src/java.base/share/classes/sun/net/www/MimeEntry.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1994, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1994, 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 @@ -26,6 +26,7 @@ package sun.net.www; import java.net.URL; import java.io.*; +import java.util.StringJoiner; import java.util.StringTokenizer; public class MimeEntry implements Cloneable { @@ -281,52 +282,34 @@ public class MimeEntry implements Cloneable { } public synchronized String toProperty() { - StringBuilder sb = new StringBuilder(); - - String separator = "; "; - boolean needSeparator = false; + StringJoiner sj = new StringJoiner("; "); int action = getAction(); if (action != MimeEntry.UNKNOWN) { - sb.append("action=" + actionKeywords[action]); - needSeparator = true; + sj.add("action=" + actionKeywords[action]); } String command = getLaunchString(); if (command != null && command.length() > 0) { - if (needSeparator) { - sb.append(separator); - } - sb.append("application=" + command); - needSeparator = true; + sj.add("application=" + command); } - if (getImageFileName() != null) { - if (needSeparator) { - sb.append(separator); - } - sb.append("icon=" + getImageFileName()); - needSeparator = true; + String image = getImageFileName(); + if (image != null) { + sj.add("icon=" + image); } String extensions = getExtensionsAsList(); if (extensions.length() > 0) { - if (needSeparator) { - sb.append(separator); - } - sb.append("file_extensions=" + extensions); - needSeparator = true; + sj.add("file_extensions=" + extensions); } String description = getDescription(); if (description != null && !description.equals(getType())) { - if (needSeparator) { - sb.append(separator); - } - sb.append("description=" + description); + sj.add("description=" + description); } - return sb.toString(); + return sj.toString(); } public String toString() { diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index 781f772c1ab..f4ade7e3dfd 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -64,6 +64,7 @@ import java.util.Iterator; import java.util.HashSet; import java.util.HashMap; import java.util.Set; +import java.util.StringJoiner; import sun.net.*; import sun.net.www.*; import sun.net.www.http.HttpClient; @@ -1386,16 +1387,11 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } List l = entry.getValue(); if (l != null && !l.isEmpty()) { - StringBuilder cookieValue = new StringBuilder(); + StringJoiner cookieValue = new StringJoiner("; "); for (String value : l) { - cookieValue.append(value).append("; "); - } - // strip off the trailing '; ' - try { - requests.add(key, cookieValue.substring(0, cookieValue.length() - 2)); - } catch (StringIndexOutOfBoundsException ignored) { - // no-op + cookieValue.add(value); } + requests.add(key, cookieValue.toString()); } } } @@ -2870,20 +2866,14 @@ public class HttpURLConnection extends java.net.HttpURLConnection { sun.misc.JavaNetHttpCookieAccess access = sun.misc.SharedSecrets.getJavaNetHttpCookieAccess(); - StringBuilder retValue = new StringBuilder(); + StringJoiner retValue = new StringJoiner(","); // RFC 2965, comma separated List cookies = access.parse(value); - boolean multipleCookies = false; for (HttpCookie cookie : cookies) { // skip HttpOnly cookies - if (cookie.isHttpOnly()) - continue; - if (multipleCookies) - retValue.append(','); // RFC 2965, comma separated - retValue.append(access.header(cookie)); - multipleCookies = true; + if (!cookie.isHttpOnly()) + retValue.add(access.header(cookie)); } - - return retValue.length() == 0 ? "" : retValue.toString(); + return retValue.toString(); } return value; diff --git a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java index 1ec1700ea67..c3067c044e0 100644 --- a/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java +++ b/jdk/src/java.base/share/classes/sun/net/www/protocol/https/HttpsURLConnectionImpl.java @@ -501,7 +501,8 @@ public class HttpsURLConnectionImpl } public boolean equals(Object obj) { - return delegate.equals(obj); + return this == obj || ((obj instanceof HttpsURLConnectionImpl) && + delegate.equals(((HttpsURLConnectionImpl)obj).delegate)); } public int hashCode() { diff --git a/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java b/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java index 7f1ae50b126..96f64ec1847 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java +++ b/jdk/src/java.base/share/classes/sun/reflect/AccessorGenerator.java @@ -69,33 +69,34 @@ class AccessorGenerator implements ClassFileConstants { protected short codeIdx; protected short exceptionsIdx; // Boxing + protected short valueOfIdx; protected short booleanIdx; - protected short booleanCtorIdx; + protected short booleanBoxIdx; protected short booleanUnboxIdx; protected short byteIdx; - protected short byteCtorIdx; + protected short byteBoxIdx; protected short byteUnboxIdx; protected short characterIdx; - protected short characterCtorIdx; + protected short characterBoxIdx; protected short characterUnboxIdx; protected short doubleIdx; - protected short doubleCtorIdx; + protected short doubleBoxIdx; protected short doubleUnboxIdx; protected short floatIdx; - protected short floatCtorIdx; + protected short floatBoxIdx; protected short floatUnboxIdx; protected short integerIdx; - protected short integerCtorIdx; + protected short integerBoxIdx; protected short integerUnboxIdx; protected short longIdx; - protected short longCtorIdx; + protected short longBoxIdx; protected short longUnboxIdx; protected short shortIdx; - protected short shortCtorIdx; + protected short shortBoxIdx; protected short shortUnboxIdx; protected final short NUM_COMMON_CPOOL_ENTRIES = (short) 30; - protected final short NUM_BOXING_CPOOL_ENTRIES = (short) 72; + protected final short NUM_BOXING_CPOOL_ENTRIES = (short) 73; // Requires that superClass has been set up protected void emitCommonConstantPoolEntries() { @@ -181,9 +182,10 @@ class AccessorGenerator implements ClassFileConstants { /** Constant pool entries required to be able to box/unbox primitive types. Note that we don't emit these if we don't need them. */ protected void emitBoxingContantPoolEntries() { + // * [UTF-8] "valueOf" // * [UTF-8] "java/lang/Boolean" // * [CONSTANT_Class_info] for above - // * [UTF-8] "(Z)V" + // * [UTF-8] "(Z)Ljava/lang/Boolean;" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "booleanValue" @@ -192,7 +194,7 @@ class AccessorGenerator implements ClassFileConstants { // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Byte" // * [CONSTANT_Class_info] for above - // * [UTF-8] "(B)V" + // * [UTF-8] "(B)Ljava/lang/Byte;" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "byteValue" @@ -201,7 +203,7 @@ class AccessorGenerator implements ClassFileConstants { // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Character" // * [CONSTANT_Class_info] for above - // * [UTF-8] "(C)V" + // * [UTF-8] "(C)Ljava/lang/Character;" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "charValue" @@ -210,7 +212,7 @@ class AccessorGenerator implements ClassFileConstants { // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Double" // * [CONSTANT_Class_info] for above - // * [UTF-8] "(D)V" + // * [UTF-8] "(D)Ljava/lang/Double;" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "doubleValue" @@ -219,7 +221,7 @@ class AccessorGenerator implements ClassFileConstants { // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Float" // * [CONSTANT_Class_info] for above - // * [UTF-8] "(F)V" + // * [UTF-8] "(F)Ljava/lang/Float;" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "floatValue" @@ -228,7 +230,7 @@ class AccessorGenerator implements ClassFileConstants { // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Integer" // * [CONSTANT_Class_info] for above - // * [UTF-8] "(I)V" + // * [UTF-8] "(I)Ljava/lang/Integer;" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "intValue" @@ -237,7 +239,7 @@ class AccessorGenerator implements ClassFileConstants { // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Long" // * [CONSTANT_Class_info] for above - // * [UTF-8] "(J)V" + // * [UTF-8] "(J)Ljava/lang/Long;" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "longValue" @@ -246,21 +248,26 @@ class AccessorGenerator implements ClassFileConstants { // * [CONSTANT_Methodref_info] for above // * [UTF-8] "java/lang/Short" // * [CONSTANT_Class_info] for above - // * [UTF-8] "(S)V" + // * [UTF-8] "(S)Ljava/lang/Short;" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above // * [UTF-8] "shortValue" // * [UTF-8] "()S" // * [CONSTANT_NameAndType_info] for above // * [CONSTANT_Methodref_info] for above + + // valueOf-method name + asm.emitConstantPoolUTF8("valueOf"); + valueOfIdx = asm.cpi(); + // Boolean asm.emitConstantPoolUTF8("java/lang/Boolean"); asm.emitConstantPoolClass(asm.cpi()); booleanIdx = asm.cpi(); - asm.emitConstantPoolUTF8("(Z)V"); - asm.emitConstantPoolNameAndType(initIdx, asm.cpi()); + asm.emitConstantPoolUTF8("(Z)Ljava/lang/Boolean;"); + asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); - booleanCtorIdx = asm.cpi(); + booleanBoxIdx = asm.cpi(); asm.emitConstantPoolUTF8("booleanValue"); asm.emitConstantPoolUTF8("()Z"); asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); @@ -271,10 +278,10 @@ class AccessorGenerator implements ClassFileConstants { asm.emitConstantPoolUTF8("java/lang/Byte"); asm.emitConstantPoolClass(asm.cpi()); byteIdx = asm.cpi(); - asm.emitConstantPoolUTF8("(B)V"); - asm.emitConstantPoolNameAndType(initIdx, asm.cpi()); + asm.emitConstantPoolUTF8("(B)Ljava/lang/Byte;"); + asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); - byteCtorIdx = asm.cpi(); + byteBoxIdx = asm.cpi(); asm.emitConstantPoolUTF8("byteValue"); asm.emitConstantPoolUTF8("()B"); asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); @@ -285,10 +292,10 @@ class AccessorGenerator implements ClassFileConstants { asm.emitConstantPoolUTF8("java/lang/Character"); asm.emitConstantPoolClass(asm.cpi()); characterIdx = asm.cpi(); - asm.emitConstantPoolUTF8("(C)V"); - asm.emitConstantPoolNameAndType(initIdx, asm.cpi()); + asm.emitConstantPoolUTF8("(C)Ljava/lang/Character;"); + asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); - characterCtorIdx = asm.cpi(); + characterBoxIdx = asm.cpi(); asm.emitConstantPoolUTF8("charValue"); asm.emitConstantPoolUTF8("()C"); asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); @@ -299,10 +306,10 @@ class AccessorGenerator implements ClassFileConstants { asm.emitConstantPoolUTF8("java/lang/Double"); asm.emitConstantPoolClass(asm.cpi()); doubleIdx = asm.cpi(); - asm.emitConstantPoolUTF8("(D)V"); - asm.emitConstantPoolNameAndType(initIdx, asm.cpi()); + asm.emitConstantPoolUTF8("(D)Ljava/lang/Double;"); + asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); - doubleCtorIdx = asm.cpi(); + doubleBoxIdx = asm.cpi(); asm.emitConstantPoolUTF8("doubleValue"); asm.emitConstantPoolUTF8("()D"); asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); @@ -313,10 +320,10 @@ class AccessorGenerator implements ClassFileConstants { asm.emitConstantPoolUTF8("java/lang/Float"); asm.emitConstantPoolClass(asm.cpi()); floatIdx = asm.cpi(); - asm.emitConstantPoolUTF8("(F)V"); - asm.emitConstantPoolNameAndType(initIdx, asm.cpi()); + asm.emitConstantPoolUTF8("(F)Ljava/lang/Float;"); + asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); - floatCtorIdx = asm.cpi(); + floatBoxIdx = asm.cpi(); asm.emitConstantPoolUTF8("floatValue"); asm.emitConstantPoolUTF8("()F"); asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); @@ -327,10 +334,10 @@ class AccessorGenerator implements ClassFileConstants { asm.emitConstantPoolUTF8("java/lang/Integer"); asm.emitConstantPoolClass(asm.cpi()); integerIdx = asm.cpi(); - asm.emitConstantPoolUTF8("(I)V"); - asm.emitConstantPoolNameAndType(initIdx, asm.cpi()); + asm.emitConstantPoolUTF8("(I)Ljava/lang/Integer;"); + asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); - integerCtorIdx = asm.cpi(); + integerBoxIdx = asm.cpi(); asm.emitConstantPoolUTF8("intValue"); asm.emitConstantPoolUTF8("()I"); asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); @@ -341,10 +348,10 @@ class AccessorGenerator implements ClassFileConstants { asm.emitConstantPoolUTF8("java/lang/Long"); asm.emitConstantPoolClass(asm.cpi()); longIdx = asm.cpi(); - asm.emitConstantPoolUTF8("(J)V"); - asm.emitConstantPoolNameAndType(initIdx, asm.cpi()); + asm.emitConstantPoolUTF8("(J)Ljava/lang/Long;"); + asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); - longCtorIdx = asm.cpi(); + longBoxIdx = asm.cpi(); asm.emitConstantPoolUTF8("longValue"); asm.emitConstantPoolUTF8("()J"); asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); @@ -355,10 +362,10 @@ class AccessorGenerator implements ClassFileConstants { asm.emitConstantPoolUTF8("java/lang/Short"); asm.emitConstantPoolClass(asm.cpi()); shortIdx = asm.cpi(); - asm.emitConstantPoolUTF8("(S)V"); - asm.emitConstantPoolNameAndType(initIdx, asm.cpi()); + asm.emitConstantPoolUTF8("(S)Ljava/lang/Short;"); + asm.emitConstantPoolNameAndType(valueOfIdx, asm.cpi()); asm.emitConstantPoolMethodref(sub(asm.cpi(), S2), asm.cpi()); - shortCtorIdx = asm.cpi(); + shortBoxIdx = asm.cpi(); asm.emitConstantPoolUTF8("shortValue"); asm.emitConstantPoolUTF8("()S"); asm.emitConstantPoolNameAndType(sub(asm.cpi(), S1), asm.cpi()); @@ -515,23 +522,23 @@ class AccessorGenerator implements ClassFileConstants { throw new InternalError("Should have found primitive type"); } - protected short ctorIndexForPrimitiveType(Class type) { + protected short boxingMethodForPrimitiveType(Class type) { if (type == Boolean.TYPE) { - return booleanCtorIdx; + return booleanBoxIdx; } else if (type == Byte.TYPE) { - return byteCtorIdx; + return byteBoxIdx; } else if (type == Character.TYPE) { - return characterCtorIdx; + return characterBoxIdx; } else if (type == Double.TYPE) { - return doubleCtorIdx; + return doubleBoxIdx; } else if (type == Float.TYPE) { - return floatCtorIdx; + return floatBoxIdx; } else if (type == Integer.TYPE) { - return integerCtorIdx; + return integerBoxIdx; } else if (type == Long.TYPE) { - return longCtorIdx; + return longBoxIdx; } else if (type == Short.TYPE) { - return shortCtorIdx; + return shortBoxIdx; } throw new InternalError("Should have found primitive type"); } diff --git a/jdk/src/java.base/share/classes/sun/reflect/MethodAccessorGenerator.java b/jdk/src/java.base/share/classes/sun/reflect/MethodAccessorGenerator.java index 55a71c84248..dfecd17423e 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/MethodAccessorGenerator.java +++ b/jdk/src/java.base/share/classes/sun/reflect/MethodAccessorGenerator.java @@ -660,9 +660,9 @@ class MethodAccessorGenerator extends AccessorGenerator { if (!isConstructor) { // Box return value if necessary if (isPrimitive(returnType)) { - cb.opc_invokespecial(ctorIndexForPrimitiveType(returnType), - typeSizeInStackSlots(returnType), - 0); + cb.opc_invokestatic(boxingMethodForPrimitiveType(returnType), + typeSizeInStackSlots(returnType), + 0); } else if (returnType == Void.TYPE) { cb.opc_aconst_null(); } diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeBooleanFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeBooleanFieldAccessorImpl.java index 8c7cdd451b5..cf929b762a9 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeBooleanFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeBooleanFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeBooleanFieldAccessorImpl extends UnsafeFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Boolean(getBoolean(obj)); + return Boolean.valueOf(getBoolean(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeByteFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeByteFieldAccessorImpl.java index 8095fc299e3..15564220ecf 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeByteFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeByteFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeByteFieldAccessorImpl extends UnsafeFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Byte(getByte(obj)); + return Byte.valueOf(getByte(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeCharacterFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeCharacterFieldAccessorImpl.java index bdf83bc27c1..bd27f00b1bd 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeCharacterFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeCharacterFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeCharacterFieldAccessorImpl extends UnsafeFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Character(getChar(obj)); + return Character.valueOf(getChar(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeDoubleFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeDoubleFieldAccessorImpl.java index df43f5967a6..a43ac29368b 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeDoubleFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeDoubleFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeDoubleFieldAccessorImpl extends UnsafeFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Double(getDouble(obj)); + return Double.valueOf(getDouble(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeFloatFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeFloatFieldAccessorImpl.java index ca7789ac666..d2410987999 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeFloatFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeFloatFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeFloatFieldAccessorImpl extends UnsafeFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Float(getFloat(obj)); + return Float.valueOf(getFloat(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeIntegerFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeIntegerFieldAccessorImpl.java index 951a2202047..df802e3b2ad 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeIntegerFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeIntegerFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeIntegerFieldAccessorImpl extends UnsafeFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Integer(getInt(obj)); + return Integer.valueOf(getInt(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeLongFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeLongFieldAccessorImpl.java index 85fcf32847a..8e76ea193fe 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeLongFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeLongFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeLongFieldAccessorImpl extends UnsafeFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Long(getLong(obj)); + return Long.valueOf(getLong(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedBooleanFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedBooleanFieldAccessorImpl.java index 8e66c7fe0f1..cc31cb4910d 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedBooleanFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedBooleanFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedBooleanFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Boolean(getBoolean(obj)); + return Boolean.valueOf(getBoolean(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedByteFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedByteFieldAccessorImpl.java index f3cc92808e5..ae239a807f4 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedByteFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedByteFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedByteFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Byte(getByte(obj)); + return Byte.valueOf(getByte(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedCharacterFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedCharacterFieldAccessorImpl.java index 247e3b231e5..e322e1d3e04 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedCharacterFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedCharacterFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedCharacterFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Character(getChar(obj)); + return Character.valueOf(getChar(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedDoubleFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedDoubleFieldAccessorImpl.java index c7b2ae1f258..1fb71f5c447 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedDoubleFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedDoubleFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedDoubleFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Double(getDouble(obj)); + return Double.valueOf(getDouble(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFloatFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFloatFieldAccessorImpl.java index c06af79e501..0b7906d4830 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFloatFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedFloatFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedFloatFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Float(getFloat(obj)); + return Float.valueOf(getFloat(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedIntegerFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedIntegerFieldAccessorImpl.java index b675158352d..df737fd0119 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedIntegerFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedIntegerFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedIntegerFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Integer(getInt(obj)); + return Integer.valueOf(getInt(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedLongFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedLongFieldAccessorImpl.java index 50fa38dcdd0..b77d4d1d9e9 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedLongFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedLongFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedLongFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Long(getLong(obj)); + return Long.valueOf(getLong(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedShortFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedShortFieldAccessorImpl.java index fddfef24f5c..c5ea9bb6caa 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedShortFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedShortFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedShortFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Short(getShort(obj)); + return Short.valueOf(getShort(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticBooleanFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticBooleanFieldAccessorImpl.java index 5b1e3f3ee8c..65dabb0fba6 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticBooleanFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticBooleanFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedStaticBooleanFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Boolean(getBoolean(obj)); + return Boolean.valueOf(getBoolean(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticByteFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticByteFieldAccessorImpl.java index a3e087e3469..136728b4594 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticByteFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticByteFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedStaticByteFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Byte(getByte(obj)); + return Byte.valueOf(getByte(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticCharacterFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticCharacterFieldAccessorImpl.java index c171064ec67..6015baf82a8 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticCharacterFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticCharacterFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedStaticCharacterFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Character(getChar(obj)); + return Character.valueOf(getChar(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticDoubleFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticDoubleFieldAccessorImpl.java index 4acd9f5221b..5433b4ec82a 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticDoubleFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticDoubleFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedStaticDoubleFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Double(getDouble(obj)); + return Double.valueOf(getDouble(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFloatFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFloatFieldAccessorImpl.java index 86eb74e89de..fe69684c1d8 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFloatFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticFloatFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedStaticFloatFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Float(getFloat(obj)); + return Float.valueOf(getFloat(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticIntegerFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticIntegerFieldAccessorImpl.java index 7ddcd8c637c..3e420f92a39 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticIntegerFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticIntegerFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedStaticIntegerFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Integer(getInt(obj)); + return Integer.valueOf(getInt(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticLongFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticLongFieldAccessorImpl.java index 97da2f256c8..d25f4ac8a56 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticLongFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticLongFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedStaticLongFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Long(getLong(obj)); + return Long.valueOf(getLong(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticShortFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticShortFieldAccessorImpl.java index 4caf4d1da00..631bd7ae333 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticShortFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeQualifiedStaticShortFieldAccessorImpl.java @@ -35,7 +35,7 @@ class UnsafeQualifiedStaticShortFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Short(getShort(obj)); + return Short.valueOf(getShort(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeShortFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeShortFieldAccessorImpl.java index d8fe8dc96ec..05ea337f49c 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeShortFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeShortFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeShortFieldAccessorImpl extends UnsafeFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Short(getShort(obj)); + return Short.valueOf(getShort(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticBooleanFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticBooleanFieldAccessorImpl.java index 741c5ff48c2..b7572b54e31 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticBooleanFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticBooleanFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeStaticBooleanFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Boolean(getBoolean(obj)); + return Boolean.valueOf(getBoolean(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticByteFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticByteFieldAccessorImpl.java index 726961ba8a2..78eeb86842f 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticByteFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticByteFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeStaticByteFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Byte(getByte(obj)); + return Byte.valueOf(getByte(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticCharacterFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticCharacterFieldAccessorImpl.java index 29b030375a7..2dd3a597681 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticCharacterFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticCharacterFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeStaticCharacterFieldAccessorImpl extends UnsafeStaticFieldAccessorIm } public Object get(Object obj) throws IllegalArgumentException { - return new Character(getChar(obj)); + return Character.valueOf(getChar(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticDoubleFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticDoubleFieldAccessorImpl.java index 34c9784466b..b07df4f987f 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticDoubleFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticDoubleFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeStaticDoubleFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Double(getDouble(obj)); + return Double.valueOf(getDouble(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFloatFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFloatFieldAccessorImpl.java index 780a794cf75..2929727b6ad 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFloatFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticFloatFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeStaticFloatFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Float(getFloat(obj)); + return Float.valueOf(getFloat(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticIntegerFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticIntegerFieldAccessorImpl.java index 1b21b766d09..963620a06fb 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticIntegerFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticIntegerFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeStaticIntegerFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl } public Object get(Object obj) throws IllegalArgumentException { - return new Integer(getInt(obj)); + return Integer.valueOf(getInt(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticLongFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticLongFieldAccessorImpl.java index 7d50ac2db9c..a8dedd060cc 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticLongFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticLongFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeStaticLongFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Long(getLong(obj)); + return Long.valueOf(getLong(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticShortFieldAccessorImpl.java b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticShortFieldAccessorImpl.java index d56d621e227..9ac6cd6533b 100644 --- a/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticShortFieldAccessorImpl.java +++ b/jdk/src/java.base/share/classes/sun/reflect/UnsafeStaticShortFieldAccessorImpl.java @@ -33,7 +33,7 @@ class UnsafeStaticShortFieldAccessorImpl extends UnsafeStaticFieldAccessorImpl { } public Object get(Object obj) throws IllegalArgumentException { - return new Short(getShort(obj)); + return Short.valueOf(getShort(obj)); } public boolean getBoolean(Object obj) throws IllegalArgumentException { diff --git a/jdk/src/java.base/share/classes/sun/security/tools/keytool/CertAndKeyGen.java b/jdk/src/java.base/share/classes/sun/security/tools/keytool/CertAndKeyGen.java index a8a748cdb14..e2b4cfbb823 100644 --- a/jdk/src/java.base/share/classes/sun/security/tools/keytool/CertAndKeyGen.java +++ b/jdk/src/java.base/share/classes/sun/security/tools/keytool/CertAndKeyGen.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -158,8 +158,8 @@ public final class CertAndKeyGen { // publicKey's format must be X.509 otherwise // the whole CertGen part of this class is broken. if (!"X.509".equalsIgnoreCase(publicKey.getFormat())) { - throw new IllegalArgumentException("publicKey's is not X.509, but " - + publicKey.getFormat()); + throw new IllegalArgumentException("Public key format is " + + publicKey.getFormat() + ", must be X.509"); } } diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/Era.java b/jdk/src/java.base/share/classes/sun/util/calendar/Era.java index a013c57afd2..3ab04110075 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/Era.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/Era.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 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 @@ -41,20 +41,15 @@ import java.util.TimeZone; * CalendarDate. * *

    The following era names are defined in this release. - * - *

    
    + * 
    {@code
      *   Calendar system         Era name         Since (in Gregorian)
      *   -----------------------------------------------------------------------
    - *   Japanese calendar       Meiji            1868-01-01 midnight local time
    - *                           Taisho           1912-07-30 midnight local time
    - *                           Showa            1926-12-26 midnight local time
    - *                           Heisei           1989-01-08 midnight local time
    - *   Julian calendar         BeforeCommonEra  -292275055-05-16T16:47:04.192Z
    - *                           CommonEra        0000-12-30 midnight local time
    - *   Taiwanese calendar      MinGuo           1911-01-01 midnight local time
    - *   Thai Buddhist calendar  BuddhistEra      -543-01-01 midnight local time
    + *   Japanese calendar       Meiji            1868-01-01T00:00:00 local time
    + *                           Taisho           1912-07-30T00:00:00 local time
    + *                           Showa            1926-12-25T00:00:00 local time
    + *                           Heisei           1989-01-08T00:00:00 local time
      *   -----------------------------------------------------------------------
    - * 
    + * }
    * * @author Masayoshi Okutsu * @since 1.5 diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java b/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java index 9a9b6637471..10cbbdceee1 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/LocalGregorianCalendar.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,7 @@ package sun.util.calendar; -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import java.util.Properties; -import java.util.StringTokenizer; +import java.security.AccessController; import java.util.TimeZone; /** @@ -39,6 +35,28 @@ import java.util.TimeZone; */ public class LocalGregorianCalendar extends BaseCalendar { + private static final Era[] JAPANESE_ERAS = { + new Era("Meiji", "M", -3218832000000L, true), + new Era("Taisho", "T", -1812153600000L, true), + new Era("Showa", "S", -1357603200000L, true), + new Era("Heisei", "H", 600220800000L, true), + }; + + private static boolean isValidEra(Era newEra, Era[] eras) { + Era last = eras[eras.length - 1]; + if (last.getSinceDate().getYear() >= newEra.getSinceDate().getYear()) { + return false; + } + // The new era name should be unique. Its abbr may not. + String newName = newEra.getName(); + for (Era era : eras) { + if (era.getName().equals(newName)) { + return false; + } + } + return true; + } + private String name; private Era[] eras; @@ -118,58 +136,70 @@ public class LocalGregorianCalendar extends BaseCalendar { } static LocalGregorianCalendar getLocalGregorianCalendar(String name) { - Properties calendarProps; - try { - calendarProps = CalendarSystem.getCalendarProperties(); - } catch (IOException | IllegalArgumentException e) { - throw new InternalError(e); - } - // Parse calendar.*.eras - String props = calendarProps.getProperty("calendar." + name + ".eras"); - if (props == null) { + // Only the Japanese calendar is supported. + if (!"japanese".equals(name)) { return null; } - List eras = new ArrayList<>(); - StringTokenizer eraTokens = new StringTokenizer(props, ";"); - while (eraTokens.hasMoreTokens()) { - String items = eraTokens.nextToken().trim(); - StringTokenizer itemTokens = new StringTokenizer(items, ","); - String eraName = null; - boolean localTime = true; - long since = 0; - String abbr = null; - while (itemTokens.hasMoreTokens()) { - String item = itemTokens.nextToken(); - int index = item.indexOf('='); - // it must be in the key=value form. - if (index == -1) { - return null; - } - String key = item.substring(0, index); - String value = item.substring(index + 1); - if ("name".equals(key)) { - eraName = value; - } else if ("since".equals(key)) { - if (value.endsWith("u")) { - localTime = false; - since = Long.parseLong(value.substring(0, value.length() - 1)); - } else { - since = Long.parseLong(value); - } - } else if ("abbr".equals(key)) { - abbr = value; - } else { - throw new RuntimeException("Unknown key word: " + key); + // Append an era to the predefined eras if it's given by the property. + String prop = AccessController.doPrivileged( + new sun.security.action.GetPropertyAction("jdk.calendar.japanese.supplemental.era")); + if (prop != null) { + Era era = parseEraEntry(prop); + if (era != null) { + if (isValidEra(era, JAPANESE_ERAS)) { + int length = JAPANESE_ERAS.length; + Era[] eras = new Era[length + 1]; + System.arraycopy(JAPANESE_ERAS, 0, eras, 0, length); + eras[length] = era; + return new LocalGregorianCalendar(name, eras); } } - Era era = new Era(eraName, abbr, since, localTime); - eras.add(era); } - Era[] eraArray = new Era[eras.size()]; - eras.toArray(eraArray); + return new LocalGregorianCalendar(name, JAPANESE_ERAS); + } - return new LocalGregorianCalendar(name, eraArray); + private static Era parseEraEntry(String entry) { + String[] keyValuePairs = entry.split(","); + String eraName = null; + boolean localTime = true; + long since = 0; + String abbr = null; + + for (String item : keyValuePairs) { + String[] keyvalue = item.split("="); + if (keyvalue.length != 2) { + return null; + } + String key = keyvalue[0].trim(); + String value = keyvalue[1].trim(); + switch (key) { + case "name": + eraName = value; + break; + case "since": + if (value.endsWith("u")) { + localTime = false; + value = value.substring(0, value.length() - 1); + } + try { + since = Long.parseLong(value); + } catch (NumberFormatException e) { + return null; + } + break; + case "abbr": + abbr = value; + break; + default: + return null; + } + } + if (eraName == null || eraName.isEmpty() + || abbr == null || abbr.isEmpty()) { + return null; + } + return new Era(eraName, abbr, since, localTime); } private LocalGregorianCalendar(String name, Era[] eras) { @@ -262,9 +292,8 @@ public class LocalGregorianCalendar extends BaseCalendar { } private boolean validateEra(Era era) { - // Validate the era - for (int i = 0; i < eras.length; i++) { - if (era == eras[i]) { + for (Era era1 : eras) { + if (era == era1) { return true; } } @@ -333,6 +362,7 @@ public class LocalGregorianCalendar extends BaseCalendar { } if (i >= 0) { ldate.setLocalEra(era); + @SuppressWarnings("null") int y = ldate.getNormalizedYear() - era.getSinceDate().getYear() + 1; ldate.setLocalYear(y); } else { diff --git a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java index 4c423b703a7..78d9f3ed6cb 100644 --- a/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java +++ b/jdk/src/java.base/share/classes/sun/util/calendar/ZoneInfoFile.java @@ -615,7 +615,9 @@ public final class ZoneInfoFile { // startTime=86400000 <= 24 hours // This: startDayOfWeek=6 // startTime=0 - // Below is the workaround, it probably slows down everyone a little + // Similar workaround needs to be applied to Africa/Cairo and + // its endDayOfWeek and endTime + // Below is the workarounds, it probably slows down everyone a little if (params[2] == 6 && params[3] == 0 && (zoneId.equals("Asia/Amman") || zoneId.equals("Asia/Gaza") || @@ -623,6 +625,13 @@ public final class ZoneInfoFile { params[2] = 5; params[3] = 86400000; } + //endDayOfWeek and endTime workaround + if (params[7] == 6 && params[8] == 0 && + (zoneId.equals("Africa/Cairo"))) { + params[7] = 5; + params[8] = 86400000; + } + } else if (nTrans > 0) { // only do this if there is something in table already if (lastyear < LASTYEAR) { // ZoneInfo has an ending entry for 2037 diff --git a/jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java index 77f7b843d64..f267212f102 100644 --- a/jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java +++ b/jdk/src/java.base/share/classes/sun/util/cldr/CLDRLocaleProviderAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,19 +25,20 @@ package sun.util.cldr; -import java.io.File; import java.security.AccessController; -import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.text.spi.BreakIteratorProvider; import java.text.spi.CollatorProvider; +import java.util.Collections; import java.util.HashSet; import java.util.Locale; -import java.util.ResourceBundle; +import java.util.ServiceLoader; import java.util.Set; import java.util.StringTokenizer; -import java.util.spi.TimeZoneNameProvider; import sun.util.locale.provider.JRELocaleProviderAdapter; import sun.util.locale.provider.LocaleProviderAdapter; +import sun.util.locale.provider.LocaleDataMetaInfo; /** * LocaleProviderAdapter implementation for the CLDR locale data. @@ -46,26 +47,31 @@ import sun.util.locale.provider.LocaleProviderAdapter; * @author Naoto Sato */ public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter { - private static final String LOCALE_DATA_JAR_NAME = "cldrdata.jar"; + + private final LocaleDataMetaInfo metaInfo; public CLDRLocaleProviderAdapter() { - final String sep = File.separator; - String localeDataJar = java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.home")) - + sep + "lib" + sep + "ext" + sep + LOCALE_DATA_JAR_NAME; - - // Peek at the installed extension directory to see if the jar file for - // CLDR resources is installed or not. - final File f = new File(localeDataJar); - boolean result = AccessController.doPrivileged( - new PrivilegedAction() { + try { + metaInfo = AccessController.doPrivileged(new PrivilegedExceptionAction() { @Override - public Boolean run() { - return f.exists(); + public LocaleDataMetaInfo run() { + for (LocaleDataMetaInfo ldmi : ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) { + if (ldmi.getType() == LocaleProviderAdapter.Type.CLDR) { + return ldmi; + } + } + return null; } }); - if (!result) { - throw new UnsupportedOperationException(); + } catch (Exception e) { + // Catch any exception, and fail gracefully as if CLDR locales do not exist. + // It's ok ignore it if something wrong happens because there always is the + // JRE or FALLBACK LocaleProviderAdapter that will do the right thing. + throw new UnsupportedOperationException(e); + } + + if (metaInfo == null) { + throw new UnsupportedOperationException("CLDR locale data could not be found."); } } @@ -90,7 +96,7 @@ public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter { @Override public Locale[] getAvailableLocales() { - Set all = createLanguageTagSet("All"); + Set all = createLanguageTagSet("AvailableLocales"); Locale[] locs = new Locale[all.size()]; int index = 0; for (String tag : all) { @@ -101,8 +107,10 @@ public class CLDRLocaleProviderAdapter extends JRELocaleProviderAdapter { @Override protected Set createLanguageTagSet(String category) { - ResourceBundle rb = ResourceBundle.getBundle("sun.util.cldr.CLDRLocaleDataMetaInfo", Locale.ROOT); - String supportedLocaleString = rb.getString(category); + String supportedLocaleString = metaInfo.availableLanguageTags(category); + if (supportedLocaleString == null) { + return Collections.emptySet(); + } Set tagset = new HashSet<>(); StringTokenizer tokens = new StringTokenizer(supportedLocaleString); while (tokens.hasMoreTokens()) { diff --git a/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java b/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java index 6eee5829095..137fd82f7dd 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/BaseLocale.java @@ -32,6 +32,7 @@ package sun.util.locale; +import java.util.StringJoiner; public final class BaseLocale { @@ -120,33 +121,20 @@ public final class BaseLocale { @Override public String toString() { - StringBuilder buf = new StringBuilder(); + StringJoiner sj = new StringJoiner(", "); if (language.length() > 0) { - buf.append("language="); - buf.append(language); + sj.add("language=" + language); } if (script.length() > 0) { - if (buf.length() > 0) { - buf.append(", "); - } - buf.append("script="); - buf.append(script); + sj.add("script=" + script); } if (region.length() > 0) { - if (buf.length() > 0) { - buf.append(", "); - } - buf.append("region="); - buf.append(region); + sj.add("region=" + region); } if (variant.length() > 0) { - if (buf.length() > 0) { - buf.append(", "); - } - buf.append("variant="); - buf.append(variant); + sj.add("variant=" + variant); } - return buf.toString(); + return sj.toString(); } @Override diff --git a/jdk/src/java.base/share/classes/sun/util/locale/LanguageTag.java b/jdk/src/java.base/share/classes/sun/util/locale/LanguageTag.java index 2247398c400..3fd7f7dbe5e 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/LanguageTag.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/LanguageTag.java @@ -37,6 +37,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.StringJoiner; public class LanguageTag { // @@ -473,21 +474,18 @@ public class LanguageTag { } if (!varitr.isDone()) { // ill-formed variant subtags - StringBuilder buf = new StringBuilder(); + StringJoiner sj = new StringJoiner(SEP); while (!varitr.isDone()) { String prvv = varitr.current(); if (!isPrivateuseSubtag(prvv)) { // cannot use private use subtag - truncated break; } - if (buf.length() > 0) { - buf.append(SEP); - } - buf.append(prvv); + sj.add(prvv); varitr.next(); } - if (buf.length() > 0) { - privuseVar = buf.toString(); + if (sj.length() > 0) { + privuseVar = sj.toString(); } } } diff --git a/jdk/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java b/jdk/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java index cc5a5685cd0..51a723aea25 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/UnicodeLocaleExtension.java @@ -1,6 +1,6 @@ /* - * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -38,6 +38,7 @@ import java.util.Map.Entry; import java.util.Set; import java.util.SortedMap; import java.util.SortedSet; +import java.util.StringJoiner; public class UnicodeLocaleExtension extends Extension { public static final char SINGLETON = 'u'; @@ -70,20 +71,20 @@ public class UnicodeLocaleExtension extends Extension { } if (!this.attributes.isEmpty() || !this.keywords.isEmpty()) { - StringBuilder sb = new StringBuilder(); + StringJoiner sj = new StringJoiner(LanguageTag.SEP); for (String attribute : this.attributes) { - sb.append(LanguageTag.SEP).append(attribute); + sj.add(attribute); } for (Entry keyword : this.keywords.entrySet()) { String key = keyword.getKey(); String value = keyword.getValue(); - sb.append(LanguageTag.SEP).append(key); + sj.add(key); if (value.length() > 0) { - sb.append(LanguageTag.SEP).append(value); + sj.add(value); } } - setValue(sb.substring(1)); // skip leading '-' + setValue(sj.toString()); } } diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java index 05ddd6e91d4..7ddcd0e3c61 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/AuxLocaleProviderAdapter.java @@ -56,7 +56,7 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter { /** * SPI implementations map */ - private ConcurrentMap, LocaleServiceProvider> providersMap = + private final ConcurrentMap, LocaleServiceProvider> providersMap = new ConcurrentHashMap<>(); /** @@ -167,7 +167,6 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter { avail.addAll(Arrays.asList(lsp.getAvailableLocales())); } } - availableLocales = avail.toArray(new Locale[0]); } // assuming caller won't mutate the array. @@ -178,7 +177,7 @@ public abstract class AuxLocaleProviderAdapter extends LocaleProviderAdapter { * A dummy locale service provider that indicates there is no * provider available */ - private static NullProvider NULL_PROVIDER = new NullProvider(); + private static final NullProvider NULL_PROVIDER = new NullProvider(); private static class NullProvider extends LocaleServiceProvider { @Override public Locale[] getAvailableLocales() { diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java index 50473cde715..efde2013320 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/JRELocaleProviderAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,17 +25,19 @@ package sun.util.locale.provider; -import java.io.File; import java.security.AccessController; -import java.security.PrivilegedAction; +import java.security.PrivilegedActionException; +import java.security.PrivilegedExceptionAction; import java.text.spi.BreakIteratorProvider; import java.text.spi.CollatorProvider; import java.text.spi.DateFormatProvider; import java.text.spi.DateFormatSymbolsProvider; import java.text.spi.DecimalFormatSymbolsProvider; import java.text.spi.NumberFormatProvider; +import java.util.Collections; import java.util.HashSet; import java.util.Locale; +import java.util.ServiceLoader; import java.util.Set; import java.util.StringTokenizer; import java.util.concurrent.ConcurrentHashMap; @@ -57,8 +59,6 @@ import sun.util.spi.CalendarProvider; */ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements ResourceBundleBasedAdapter { - private static final String LOCALE_DATA_JAR_NAME = "localedata.jar"; - private final ConcurrentMap> langtagSets = new ConcurrentHashMap<>(); @@ -355,23 +355,56 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R } protected Set createLanguageTagSet(String category) { - String supportedLocaleString = LocaleDataMetaInfo.getSupportedLocaleString(category); + String supportedLocaleString = createSupportedLocaleString(category); + if (supportedLocaleString == null) { + return Collections.emptySet(); + } Set tagset = new HashSet<>(); StringTokenizer tokens = new StringTokenizer(supportedLocaleString); while (tokens.hasMoreTokens()) { - String token = tokens.nextToken(); - if (token.equals("|")) { - if (isNonENLangSupported()) { - continue; - } - break; - } - tagset.add(token); + tagset.add(tokens.nextToken()); } return tagset; } + private static String createSupportedLocaleString(String category) { + // Directly call English tags, as we know it's in the base module. + String supportedLocaleString = EnLocaleDataMetaInfo.getSupportedLocaleString(category); + + // Use ServiceLoader to dynamically acquire installed locales' tags. + try { + String nonENTags = AccessController.doPrivileged(new PrivilegedExceptionAction() { + @Override + public String run() { + String tags = null; + for (LocaleDataMetaInfo ldmi : + ServiceLoader.loadInstalled(LocaleDataMetaInfo.class)) { + if (ldmi.getType() == LocaleProviderAdapter.Type.JRE) { + String t = ldmi.availableLanguageTags(category); + if (t != null) { + if (tags == null) { + tags = t; + } else { + tags += " " + t; + } + } + } + } + return tags; + } + }); + + if (nonENTags != null) { + supportedLocaleString += " " + nonENTags; + } + } catch (Exception e) { + // catch any exception, and ignore them as if non-EN locales do not exist. + } + + return supportedLocaleString; + } + /** * Lazy load available locales. */ @@ -383,27 +416,17 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R private static Locale[] createAvailableLocales() { /* - * Gets the locale string list from LocaleDataMetaInfo class and then + * Gets the locale string list from LocaleDataMetaInfo classes and then * contructs the Locale array and a set of language tags based on the * locale string returned above. */ - String supportedLocaleString = LocaleDataMetaInfo.getSupportedLocaleString("AvailableLocales"); + String supportedLocaleString = createSupportedLocaleString("AvailableLocales"); if (supportedLocaleString.length() == 0) { throw new InternalError("No available locales for JRE"); } - /* - * Look for "|" and construct a new locale string list. - */ - int barIndex = supportedLocaleString.indexOf('|'); - StringTokenizer localeStringTokenizer; - if (isNonENLangSupported()) { - localeStringTokenizer = new StringTokenizer(supportedLocaleString.substring(0, barIndex) - + supportedLocaleString.substring(barIndex + 1)); - } else { - localeStringTokenizer = new StringTokenizer(supportedLocaleString.substring(0, barIndex)); - } + StringTokenizer localeStringTokenizer = new StringTokenizer(supportedLocaleString); int length = localeStringTokenizer.countTokens(); Locale[] locales = new Locale[length + 1]; @@ -426,39 +449,4 @@ public class JRELocaleProviderAdapter extends LocaleProviderAdapter implements R } return locales; } - - private static volatile Boolean isNonENSupported = null; - - /* - * Returns true if the non EN resources jar file exists in jre - * extension directory. @returns true if the jar file is there. Otherwise, - * returns false. - */ - private static boolean isNonENLangSupported() { - if (isNonENSupported == null) { - synchronized (JRELocaleProviderAdapter.class) { - if (isNonENSupported == null) { - final String sep = File.separator; - String localeDataJar = - java.security.AccessController.doPrivileged( - new sun.security.action.GetPropertyAction("java.home")) - + sep + "lib" + sep + "ext" + sep + LOCALE_DATA_JAR_NAME; - - /* - * Peek at the installed extension directory to see if - * localedata.jar is installed or not. - */ - final File f = new File(localeDataJar); - isNonENSupported = - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Boolean run() { - return f.exists(); } - }); - } - } - } - return isNonENSupported; - } -} diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template index 17d9af65817..7509b602b6c 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo-XLocales.java.template @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 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 @@ -30,19 +30,17 @@ * each resource in sun.util.resources & sun.text.resources. * It is used to avoid loading non-existent localized resources so that * jar files won't be opened unnecessary to look up them. - * - * @since 1.6 */ -package sun.util.locale.provider; +package #Package#; import java.util.HashMap; +import java.util.Map; +import sun.util.locale.provider.LocaleDataMetaInfo; +import static sun.util.locale.provider.LocaleProviderAdapter.Type; +public class #Lang#LocaleDataMetaInfo implements LocaleDataMetaInfo { -public class LocaleDataMetaInfo { - - private static final HashMap resourceNameToLocales = - new HashMap(7); - + private static final Map resourceNameToLocales = new HashMap<>(9); static { /* During JDK build time, #XXX_YYY# will be replaced by a string contain all the locales @@ -52,32 +50,51 @@ public class LocaleDataMetaInfo { look up locale string such as "en" could be based on if it contains " en ". */ resourceNameToLocales.put("FormatData", - " #FormatData_ENLocales# | #FormatData_NonENLocales# "); + " #FormatData_Locales# "); resourceNameToLocales.put("CollationData", - " #CollationData_ENLocales# | #CollationData_NonENLocales# "); + " #CollationData_Locales# "); + + resourceNameToLocales.put("BreakIteratorInfo", + " #BreakIteratorInfo_Locales# "); + + resourceNameToLocales.put("BreakIteratorRules", + " #BreakIteratorRules_Locales# "); resourceNameToLocales.put("TimeZoneNames", - " #TimeZoneNames_ENLocales# | #TimeZoneNames_NonENLocales# "); + " #TimeZoneNames_Locales# "); resourceNameToLocales.put("LocaleNames", - " #LocaleNames_ENLocales# | #LocaleNames_NonENLocales# "); + " #LocaleNames_Locales# "); resourceNameToLocales.put("CurrencyNames", - " #CurrencyNames_ENLocales# | #CurrencyNames_NonENLocales# "); + " #CurrencyNames_Locales# "); resourceNameToLocales.put("CalendarData", - " #CalendarData_ENLocales# | #CalendarData_NonENLocales# "); + " #CalendarData_Locales# "); resourceNameToLocales.put("AvailableLocales", - " #AvailableLocales_ENLocales# | #AvailableLocales_NonENLocales# "); + " #AvailableLocales_Locales# "); } /* + * Gets the supported locales string based on the availability of + * locale data resource bundles for each resource name. + * * @param resourceName the resource name * @return the supported locale string for the passed in resource. */ public static String getSupportedLocaleString(String resourceName) { - return resourceNameToLocales.get(resourceName); + return resourceNameToLocales.getOrDefault(resourceName, ""); + } + + @Override + public Type getType() { + return Type.JRE; +} + + @Override + public String availableLanguageTags(String category) { + return getSupportedLocaleString(category); } } diff --git a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ReferenceTypeSpec.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo.java similarity index 62% rename from jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ReferenceTypeSpec.java rename to jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo.java index 7ad277e341f..149348f66d0 100644 --- a/jdk/src/demo/share/jpda/com/sun/tools/example/debug/bdi/ReferenceTypeSpec.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleDataMetaInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -23,28 +23,27 @@ * questions. */ -/* - * This source code is provided to illustrate the usage of a given feature - * or technique and has been deliberately simplified. Additional steps - * required for a production-quality application, such as security checks, - * input validation and proper error handling, might not be present in - * this sample code. +package sun.util.locale.provider; + +/** + * LocaleData meta info SPI + * + * @author Naoto Sato */ +public interface LocaleDataMetaInfo { - -package com.sun.tools.example.debug.bdi; - -import com.sun.jdi.*; - -interface ReferenceTypeSpec { /** - * Does the specified ReferenceType match this spec. + * Returns the type of LocaleProviderAdapter for which this LocaleData + * provides the data. + * @return type The type of the adapter. */ - boolean matches(ReferenceType refType); + public LocaleProviderAdapter.Type getType(); - @Override - int hashCode(); - - @Override - boolean equals(Object obj); + /** + * Returns the string concatenation of the supported language tags in + * this LocaleData instance + * @param category category of the locale data. + * @return concatenated language tags, separated by a space. + */ + public String availableLanguageTags(String category); } diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java index b7ba7361d2b..3f7222172d7 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/LocaleProviderAdapter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 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 @@ -295,7 +295,7 @@ public abstract class LocaleProviderAdapter { * A utility method for implementing the default LocaleServiceProvider.isSupportedLocale * for the JRE, CLDR, and FALLBACK adapters. */ - static boolean isSupportedLocale(Locale locale, LocaleProviderAdapter.Type type, Set langtags) { + public static boolean isSupportedLocale(Locale locale, LocaleProviderAdapter.Type type, Set langtags) { assert type == Type.JRE || type == Type.CLDR || type == Type.FALLBACK; if (Locale.ROOT.equals(locale)) { return true; diff --git a/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java b/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java index f8c68fa35c2..a1962e463da 100644 --- a/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java +++ b/jdk/src/java.base/share/classes/sun/util/locale/provider/RuleBasedBreakIterator.java @@ -547,12 +547,7 @@ class RuleBasedBreakIterator extends BreakIterator { */ @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append('['); - sb.append("checksum=0x"); - sb.append(Long.toHexString(checksum)); - sb.append(']'); - return sb.toString(); + return "[checksum=0x" + Long.toHexString(checksum) + ']'; } /** diff --git a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java index 00ba6dec959..75ee2f018ba 100644 --- a/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java +++ b/jdk/src/java.base/share/classes/sun/util/resources/LocaleData.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -48,8 +48,10 @@ import java.util.List; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; -import sun.util.locale.provider.LocaleDataMetaInfo; +import java.util.Set; +import sun.util.locale.provider.JRELocaleProviderAdapter; import sun.util.locale.provider.LocaleProviderAdapter; +import static sun.util.locale.provider.LocaleProviderAdapter.Type.CLDR; import static sun.util.locale.provider.LocaleProviderAdapter.Type.JRE; /** @@ -204,35 +206,23 @@ public class LocaleData { @Override public List getCandidateLocales(String baseName, Locale locale) { List candidates = super.getCandidateLocales(baseName, locale); - /* Get the locale string list from LocaleDataMetaInfo class. */ - String localeString = LocaleDataMetaInfo.getSupportedLocaleString(baseName); - - if (localeString != null && localeString.length() != 0) { - for (Iterator l = candidates.iterator(); l.hasNext();) { - Locale loc = l.next(); - String lstr; - if (loc.getScript().length() > 0) { - lstr = loc.toLanguageTag().replace('-', '_'); - } else { - lstr = loc.toString(); - int idx = lstr.indexOf("_#"); - if (idx >= 0) { - lstr = lstr.substring(0, idx); - } - } - /* Every locale string in the locale string list returned from - the above getSupportedLocaleString is enclosed - within two white spaces so that we could check some locale - such as "en". - */ - if (lstr.length() != 0 && localeString.indexOf(" " + lstr + " ") == -1) { - l.remove(); + // Weed out Locales which are known to have no resource bundles + int lastDot = baseName.lastIndexOf('.'); + String category = (lastDot >= 0) ? baseName.substring(lastDot + 1) : baseName; + LocaleProviderAdapter.Type type = baseName.contains(DOTCLDR) ? CLDR : JRE; + LocaleProviderAdapter adapter = LocaleProviderAdapter.forType(type); + Set langtags = ((JRELocaleProviderAdapter)adapter).getLanguageTagSet(category); + if (!langtags.isEmpty()) { + for (Iterator itr = candidates.iterator(); itr.hasNext();) { + if (!LocaleProviderAdapter.isSupportedLocale(itr.next(), type, langtags)) { + itr.remove(); } } } + // Force fallback to Locale.ENGLISH for CLDR time zone names support if (locale.getLanguage() != "en" - && baseName.contains(CLDR) && baseName.endsWith("TimeZoneNames")) { + && type == CLDR && category.equals("TimeZoneNames")) { candidates.add(candidates.size() - 1, Locale.ENGLISH); } return candidates; @@ -254,7 +244,7 @@ public class LocaleData { return null; } - private static final String CLDR = ".cldr"; + private static final String DOTCLDR = ".cldr"; /** * Changes baseName to its per-language package name and @@ -275,8 +265,8 @@ public class LocaleData { assert JRE.getUtilResourcesPackage().length() == JRE.getTextResourcesPackage().length(); int index = JRE.getUtilResourcesPackage().length(); - if (baseName.indexOf(CLDR, index) > 0) { - index += CLDR.length(); + if (baseName.indexOf(DOTCLDR, index) > 0) { + index += DOTCLDR.length(); } newBaseName = baseName.substring(0, index + 1) + lang + baseName.substring(index); diff --git a/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java index 298a233d850..9ab92c93620 100644 --- a/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java +++ b/jdk/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java @@ -47,9 +47,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String ACT[] = new String[] {"Acre Time", "ACT", "Acre Summer Time", "ACST", "Acre Time", "ACT"}; - String ADELAIDE[] = new String[] {"Central Standard Time (South Australia)", "CST", - "Central Summer Time (South Australia)", "CST", - "Central Time (South Australia)", "CT"}; + String ADELAIDE[] = new String[] {"Australian Central Standard Time (South Australia)", "ACST", + "Australian Central Daylight Time (South Australia)", "ACDT", + "Australian Central Time (South Australia)", "ACT"}; String AGT[] = new String[] {"Argentine Time", "ART", "Argentine Summer Time", "ARST", "Argentine Time", "ART"}; @@ -71,12 +71,12 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String BDT[] = new String[] {"Bangladesh Time", "BDT", "Bangladesh Summer Time", "BDST", "Bangladesh Time", "BDT"}; - String BRISBANE[] = new String[] {"Eastern Standard Time (Queensland)", "EST", - "Eastern Summer Time (Queensland)", "EST", - "Eastern Time (Queensland)", "ET"}; - String BROKEN_HILL[] = new String[] {"Central Standard Time (South Australia/New South Wales)", "CST", - "Central Summer Time (South Australia/New South Wales)", "CST", - "Central Time (South Australia/New South Wales)", "CT"}; + String BRISBANE[] = new String[] {"Australian Eastern Standard Time (Queensland)", "AEST", + "Australian Eastern Daylight Time (Queensland)", "AEDT", + "Australian Eastern Time (Queensland)", "AET"}; + String BROKEN_HILL[] = new String[] {"Australian Central Standard Time (South Australia/New South Wales)", "ACST", + "Australian Central Daylight Time (South Australia/New South Wales)", "ACDT", + "Australian Central Time (South Australia/New South Wales)", "ACT"}; String BRT[] = new String[] {"Brasilia Time", "BRT", "Brasilia Summer Time", "BRST", "Brasilia Time", "BRT"}; @@ -110,9 +110,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String CUBA[] = new String[] {"Cuba Standard Time", "CST", "Cuba Daylight Time", "CDT", "Cuba Time", "CT"}; - String DARWIN[] = new String[] {"Central Standard Time (Northern Territory)", "CST", - "Central Summer Time (Northern Territory)", "CST", - "Central Time (Northern Territory)", "CT"}; + String DARWIN[] = new String[] {"Australian Central Standard Time (Northern Territory)", "ACST", + "Australian Central Daylight Time (Northern Territory)", "ACDT", + "Australian Central Time (Northern Territory)", "ACT"}; String DUBLIN[] = new String[] {"Greenwich Mean Time", "GMT", "Irish Summer Time", "IST", "Irish Time", "IT"}; @@ -131,9 +131,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String EST[] = new String[] {"Eastern Standard Time", "EST", "Eastern Daylight Time", "EDT", "Eastern Time", "ET"}; - String EST_NSW[] = new String[] {"Eastern Standard Time (New South Wales)", "EST", - "Eastern Summer Time (New South Wales)", "EST", - "Eastern Time (New South Wales)", "ET"}; + String EST_NSW[] = new String[] {"Australian Eastern Standard Time (New South Wales)", "AEST", + "Australian Eastern Daylight Time (New South Wales)", "AEDT", + "Australian Eastern Time (New South Wales)", "AET"}; String FET[] = new String[] {"Further-eastern European Time", "FET", "Further-eastern European Summer Time", "FEST", "Further-eastern European Time", "FET"}; @@ -167,6 +167,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String IRT[] = new String[] {"Iran Standard Time", "IRST", "Iran Daylight Time", "IRDT", "Iran Time", "IRT"}; + String IRKT[] = new String[] {"Irkutsk Time", "IRKT", + "Irkutsk Summer Time", "IRKST", + "Irkutsk Time", "IRKT"}; String ISRAEL[] = new String[] {"Israel Standard Time", "IST", "Israel Daylight Time", "IDT", "Israel Time", "IT"}; @@ -176,11 +179,14 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String JST[] = new String[] {"Japan Standard Time", "JST", "Japan Daylight Time", "JDT", "Japan Time", "JT"}; + String KRAT[] = new String[] {"Krasnoyarsk Time", "KRAT", + "Krasnoyarsk Summer Time", "KRAST", + "Krasnoyarsk Time", "KRAT"}; String KST[] = new String[] {"Korea Standard Time", "KST", "Korea Daylight Time", "KDT", "Korea Time", "KT"}; String LORD_HOWE[] = new String[] {"Lord Howe Standard Time", "LHST", - "Lord Howe Summer Time", "LHST", + "Lord Howe Daylight Time", "LHDT", "Lord Howe Time", "LHT"}; String MHT[] = new String[] {"Marshall Islands Time", "MHT", "Marshall Islands Summer Time", "MHST", @@ -230,21 +236,15 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String SGT[] = new String[] {"Singapore Time", "SGT", "Singapore Summer Time", "SGST", "Singapore Time", "SGT"}; - String SLST[] = new String[] {"Greenwich Mean Time", "GMT", - "Sierra Leone Summer Time", "SLST", - "Sierra Leone Time", "SLT"}; - String TASMANIA[] = new String[] {"Eastern Standard Time (Tasmania)", "EST", - "Eastern Summer Time (Tasmania)", "EST", - "Eastern Time (Tasmania)", "ET"}; + String TASMANIA[] = new String[] {"Australian Eastern Standard Time (Tasmania)", "AEST", + "Australian Eastern Daylight Time (Tasmania)", "AEDT", + "Australian Eastern Time (Tasmania)", "AET"}; String TMT[] = new String[] {"Turkmenistan Time", "TMT", "Turkmenistan Summer Time", "TMST", "Turkmenistan Time", "TMT"}; String ULAT[]= new String[] {"Ulaanbaatar Time", "ULAT", "Ulaanbaatar Summer Time", "ULAST", "Ulaanbaatar Time", "ULAT"}; - String WART[] = new String[] {"Western Argentine Time", "WART", - "Western Argentine Summer Time", "WARST", - "Western Argentine Time", "WART"}; String WAT[] = new String[] {"Western African Time", "WAT", "Western African Summer Time", "WAST", "Western African Time", "WAT"}; @@ -254,27 +254,30 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { String WIT[] = new String[] {"West Indonesia Time", "WIB", "West Indonesia Summer Time", "WIST", "West Indonesia Time", "WIB"}; - String WST_AUS[] = new String[] {"Western Standard Time (Australia)", "WST", - "Western Summer Time (Australia)", "WST", - "Western Time (Australia)", "WT"}; + String WST_AUS[] = new String[] {"Australian Western Standard Time", "AWST", + "Australian Western Daylight Time", "AWDT", + "Australian Western Time", "AWT"}; String SAMOA[] = new String[] {"Samoa Standard Time", "SST", "Samoa Daylight Time", "SDT", "Samoa Time", "ST"}; - String WST_SAMOA[] = new String[] {"West Samoa Time", "WST", + String WST_SAMOA[] = new String[] {"West Samoa Standard Time", "WSST", "West Samoa Daylight Time", "WSDT", "West Samoa Time", "WST"}; String ChST[] = new String[] {"Chamorro Standard Time", "ChST", "Chamorro Daylight Time", "ChDT", "Chamorro Time", "ChT"}; - String VICTORIA[] = new String[] {"Eastern Standard Time (Victoria)", "EST", - "Eastern Summer Time (Victoria)", "EST", - "Eastern Time (Victoria)", "ET"}; + String VICTORIA[] = new String[] {"Australian Eastern Standard Time (Victoria)", "AEST", + "Australian Eastern Daylight Time (Victoria)", "AEDT", + "Australian Eastern Time (Victoria)", "AET"}; String UTC[] = new String[] {"Coordinated Universal Time", "UTC", "Coordinated Universal Time", "UTC", "Coordinated Universal Time", "UTC"}; String UZT[] = new String[] {"Uzbekistan Time", "UZT", "Uzbekistan Summer Time", "UZST", "Uzbekistan Time", "UZT"}; + String XJT[] = new String[] {"Xinjiang Standard Time", "XJT", + "Xinjiang Daylight Time", "XJDT", + "Xinjiang Time", "XJT"}; return new Object[][] { {"America/Los_Angeles", PST}, @@ -336,7 +339,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Africa/Djibouti", EAT}, {"Africa/Douala", WAT}, {"Africa/El_Aaiun", WET}, - {"Africa/Freetown", SLST}, + {"Africa/Freetown", GMT}, {"Africa/Gaborone", CAT}, {"Africa/Harare", CAT}, {"Africa/Johannesburg", SAST}, @@ -437,7 +440,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Western Greenland Summer Time", "WGST", "Western Greenland Time", "WGT"}}, {"America/Goose_Bay", AST}, - {"America/Grand_Turk", EST}, + {"America/Grand_Turk", AST}, {"America/Grenada", AST}, {"America/Guadeloupe", AST}, {"America/Guatemala", CST}, @@ -484,9 +487,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"America/Mendoza", AGT}, {"America/Menominee", CST}, {"America/Merida", CST}, - {"America/Metlakatla", new String[] {"Metlakatla Standard Time", "MeST", - "Metlakatla Daylight Time", "MeDT", - "Metlakatla Time", "MeT"}}, + {"America/Metlakatla", PST}, {"America/Mexico_City", CST}, {"America/Miquelon", new String[] {"Pierre & Miquelon Standard Time", "PMST", "Pierre & Miquelon Daylight Time", "PMDT", @@ -555,8 +556,8 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville Time", "DDUT", "Dumont-d'Urville Summer Time", "DDUST", "Dumont-d'Urville Time", "DDUT"}}, - {"Antarctica/Macquarie", new String[] {"Macquarie Island Time", "MIST", - "Macquarie Island Summer Time", "MIST", + {"Antarctica/Macquarie", new String[] {"Macquarie Island Standard Time", "MIST", + "Macquarie Island Daylight Time", "MIDT", "Macquarie Island Time", "MIST"}}, {"Antarctica/Mawson", new String[] {"Mawson Time", "MAWT", "Mawson Summer Time", "MAWST", @@ -607,6 +608,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Brunei Summer Time", "BNST", "Brunei Time", "BNT"}}, {"Asia/Calcutta", IST}, + {"Asia/Chita", IRKT}, {"Asia/Choibalsan", new String[] {"Choibalsan Time", "CHOT", "Choibalsan Summer Time", "CHOST", "Choibalsan Time", "CHOT"}}, @@ -631,9 +633,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Asia/Hovd", new String[] {"Hovd Time", "HOVT", "Hovd Summer Time", "HOVST", "Hovd Time", "HOVT"}}, - {"Asia/Irkutsk", new String[] {"Irkutsk Time", "IRKT", - "Irkutsk Summer Time", "IRKST", - "Irkutsk Time", "IRKT"}}, + {"Asia/Irkutsk", IRKT}, {"Asia/Istanbul", EET}, {"Asia/Jakarta", WIT}, {"Asia/Jayapura", new String[] {"East Indonesia Time", "WIT", @@ -646,7 +646,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Petropavlovsk-Kamchatski Summer Time", "PETST", "Petropavlovsk-Kamchatski Time", "PETT"}}, {"Asia/Karachi", PKT}, - {"Asia/Kashgar", CTT}, + {"Asia/Kashgar", XJT}, {"Asia/Kathmandu", NPT}, {"Asia/Katmandu", NPT}, {"Asia/Khandyga", new String[] {"Khandyga Time", "YAKT", @@ -654,9 +654,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Khandyga Time", "YAKT"}}, {"Asia/Kolkata", IST}, - {"Asia/Krasnoyarsk", new String[] {"Krasnoyarsk Time", "KRAT", - "Krasnoyarsk Summer Time", "KRAST", - "Krasnoyarsk Time", "KRAT"}}, + {"Asia/Krasnoyarsk", KRAT}, {"Asia/Kuala_Lumpur", MYT}, {"Asia/Kuching", MYT}, {"Asia/Kuwait", ARAST}, @@ -671,7 +669,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { "Philippines Time", "PHT"}}, {"Asia/Muscat", GST}, {"Asia/Nicosia", EET}, - {"Asia/Novokuznetsk", NOVT}, + {"Asia/Novokuznetsk", KRAT}, {"Asia/Novosibirsk", NOVT}, {"Asia/Oral", new String[] {"Oral Time", "ORAT", "Oral Summer Time", "ORAST", @@ -697,6 +695,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Asia/Samarkand", UZT}, {"Asia/Seoul", KST}, {"Asia/Singapore", SGT}, + {"Asia/Srednekolymsk", new String[] {"Srednekolymsk Time", "SRET", + "Srednekolymsk Daylight Time", "SREDT", + "Srednekolymsk Time", "SRET"}}, {"Asia/Taipei", CTT}, {"Asia/Tel_Aviv", ISRAEL}, {"Asia/Tashkent", UZT}, @@ -709,7 +710,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Asia/Ujung_Pandang", CIT}, {"Asia/Ulaanbaatar", ULAT}, {"Asia/Ulan_Bator", ULAT}, - {"Asia/Urumqi", CTT}, + {"Asia/Urumqi", XJT}, {"Asia/Ust-Nera", new String[] {"Ust-Nera Time", "VLAT", "Ust-Nera Summer Time", "VLAST", "Ust-Nera Time", "VLAT"}}, @@ -751,9 +752,9 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Australia/Canberra", EST_NSW}, {"Australia/Currie", EST_NSW}, {"Australia/Darwin", DARWIN}, - {"Australia/Eucla", new String[] {"Central Western Standard Time (Australia)", "CWST", - "Central Western Summer Time (Australia)", "CWST", - "Central Western Time (Australia)", "CWT"}}, + {"Australia/Eucla", new String[] {"Australian Central Western Standard Time", "ACWST", + "Australian Central Western Daylight Time", "ACWDT", + "Australian Central Western Time", "ACWT"}}, {"Australia/Hobart", TASMANIA}, {"Australia/LHI", LORD_HOWE}, {"Australia/Lindeman", BRISBANE}, @@ -819,7 +820,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Europe/Isle_of_Man", GMTBST}, {"Europe/Istanbul", EET}, {"Europe/Jersey", GMTBST}, - {"Europe/Kaliningrad", FET}, + {"Europe/Kaliningrad", EET}, {"Europe/Kiev", EET}, {"Europe/Lisbon", WET}, {"Europe/Ljubljana", CET}, @@ -854,9 +855,7 @@ public final class TimeZoneNames extends TimeZoneNamesBundle { {"Europe/Vatican", CET}, {"Europe/Vienna", CET}, {"Europe/Vilnius", EET}, - {"Europe/Volgograd", new String[] {"Volgograd Time", "VOLT", - "Volgograd Summer Time", "VOLST", - "Volgograd Time", "VOLT"}}, + {"Europe/Volgograd", MSK}, {"Europe/Warsaw", CET}, {"Europe/Zagreb", CET}, {"Europe/Zaporozhye", EET}, diff --git a/jdk/src/java.base/share/conf/calendars.properties b/jdk/src/java.base/share/conf/calendars.properties index 49f68aca492..46bb0e2bd60 100644 --- a/jdk/src/java.base/share/conf/calendars.properties +++ b/jdk/src/java.base/share/conf/calendars.properties @@ -1,4 +1,4 @@ -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 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 @@ -22,37 +22,6 @@ # questions. # -# -# Japanese imperial calendar -# -# Meiji since 1868-01-01 00:00:00 local time (Gregorian) -# Taisho since 1912-07-30 00:00:00 local time (Gregorian) -# Showa since 1926-12-25 00:00:00 local time (Gregorian) -# Heisei since 1989-01-08 00:00:00 local time (Gregorian) -calendar.japanese.type: LocalGregorianCalendar -calendar.japanese.eras: \ - name=Meiji,abbr=M,since=-3218832000000; \ - name=Taisho,abbr=T,since=-1812153600000; \ - name=Showa,abbr=S,since=-1357603200000; \ - name=Heisei,abbr=H,since=600220800000 - -# -# Taiwanese calendar -# Minguo since 1911-01-01 00:00:00 local time (Gregorian) -calendar.taiwanese.type: LocalGregorianCalendar -calendar.taiwanese.eras: \ - name=MinGuo,since=-1830384000000 - -# -# Thai Buddhist calendar -# Buddhist Era since -542-01-01 00:00:00 local time (Gregorian) -calendar.thai-buddhist.type: LocalGregorianCalendar -calendar.thai-buddhist.eras: \ - name=BuddhistEra,abbr=B.E.,since=-79302585600000 -calendar.thai-buddhist.year-boundary: \ - day1=4-1,since=-79302585600000; \ - day1=1-1,since=-915148800000 - # # Hijrah calendars # diff --git a/jdk/src/java.base/share/conf/security/java.security-windows b/jdk/src/java.base/share/conf/security/java.security similarity index 94% rename from jdk/src/java.base/share/conf/security/java.security-windows rename to jdk/src/java.base/share/conf/security/java.security index bd34766c653..7f7bc9c383d 100644 --- a/jdk/src/java.base/share/conf/security/java.security-windows +++ b/jdk/src/java.base/share/conf/security/java.security @@ -65,16 +65,25 @@ # # List of providers and their preference orders (see above): # -security.provider.1=sun.security.provider.Sun -security.provider.2=sun.security.rsa.SunRsaSign -security.provider.3=sun.security.ec.SunEC -security.provider.4=com.sun.net.ssl.internal.ssl.Provider -security.provider.5=com.sun.crypto.provider.SunJCE -security.provider.6=sun.security.jgss.SunProvider -security.provider.7=com.sun.security.sasl.Provider -security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI -security.provider.9=sun.security.smartcardio.SunPCSC -security.provider.10=sun.security.mscapi.SunMSCAPI +#ifdef solaris +security.provider.tbd=com.oracle.security.ucrypto.UcryptoProvider ${java.home}/lib/security/ucrypto-solaris.cfg +security.provider.tbd=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/sunpkcs11-solaris.cfg +#endif +security.provider.tbd=sun.security.provider.Sun +security.provider.tbd=sun.security.rsa.SunRsaSign +security.provider.tbd=sun.security.ec.SunEC +security.provider.tbd=com.sun.net.ssl.internal.ssl.Provider +security.provider.tbd=com.sun.crypto.provider.SunJCE +security.provider.tbd=sun.security.jgss.SunProvider +security.provider.tbd=com.sun.security.sasl.Provider +security.provider.tbd=org.jcp.xml.dsig.internal.dom.XMLDSigRI +security.provider.tbd=sun.security.smartcardio.SunPCSC +#ifdef windows +security.provider.tbd=sun.security.mscapi.SunMSCAPI +#endif +#ifdef macosx +security.provider.tbd=apple.security.AppleProvider +#endif # # Sun Provider SecureRandom seed source. @@ -127,7 +136,12 @@ securerandom.source=file:/dev/random # This is a comma-separated list of algorithm and/or algorithm:provider # entries. # +#ifdef windows securerandom.strongAlgorithms=Windows-PRNG:SunMSCAPI,SHA1PRNG:SUN +#endif +#ifndef windows +securerandom.strongAlgorithms=NativePRNGBlocking:SUN +#endif # # Class to instantiate as the javax.security.auth.login.Configuration @@ -212,7 +226,9 @@ package.access=sun.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools.,\ com.sun.activation.registries.,\ - com.sun.java.accessibility. +#ifdef macosx + apple.,\ +#endif # # List of comma-separated packages that start with or equal this string @@ -259,7 +275,9 @@ package.definition=sun.,\ jdk.nashorn.internal.,\ jdk.nashorn.tools.,\ com.sun.activation.registries.,\ - com.sun.java.accessibility. +#ifdef macosx + apple.,\ +#endif # # Determines whether this properties file can be appended to diff --git a/jdk/src/java.base/share/conf/security/java.security-aix b/jdk/src/java.base/share/conf/security/java.security-aix deleted file mode 100644 index 77540a3e506..00000000000 --- a/jdk/src/java.base/share/conf/security/java.security-aix +++ /dev/null @@ -1,496 +0,0 @@ -# -# This is the "master security properties file". -# -# An alternate java.security properties file may be specified -# from the command line via the system property -# -# -Djava.security.properties= -# -# This properties file appends to the master security properties file. -# If both properties files specify values for the same key, the value -# from the command-line properties file is selected, as it is the last -# one loaded. -# -# Also, if you specify -# -# -Djava.security.properties== (2 equals), -# -# then that properties file completely overrides the master security -# properties file. -# -# To disable the ability to specify an additional properties file from -# the command line, set the key security.overridePropertiesFile -# to false in the master security properties file. It is set to true -# by default. - -# In this file, various security properties are set for use by -# java.security classes. This is where users can statically register -# Cryptography Package Providers ("providers" for short). The term -# "provider" refers to a package or set of packages that supply a -# concrete implementation of a subset of the cryptography aspects of -# the Java Security API. A provider may, for example, implement one or -# more digital signature algorithms or message digest algorithms. -# -# Each provider must implement a subclass of the Provider class. -# To register a provider in this master security properties file, -# specify the Provider subclass name and priority in the format -# -# security.provider.= -# -# This declares a provider, and specifies its preference -# order n. The preference order is the order in which providers are -# searched for requested algorithms (when no specific provider is -# requested). The order is 1-based; 1 is the most preferred, followed -# by 2, and so on. -# -# must specify the subclass of the Provider class whose -# constructor sets the values of various properties that are required -# for the Java Security API to look up the algorithms or other -# facilities implemented by the provider. -# -# There must be at least one provider specification in java.security. -# There is a default provider that comes standard with the JDK. It -# is called the "SUN" provider, and its Provider subclass -# named Sun appears in the sun.security.provider package. Thus, the -# "SUN" provider is registered via the following: -# -# security.provider.1=sun.security.provider.Sun -# -# (The number 1 is used for the default provider.) -# -# Note: Providers can be dynamically registered instead by calls to -# either the addProvider or insertProviderAt method in the Security -# class. - -# -# List of providers and their preference orders (see above): -# -security.provider.1=sun.security.provider.Sun -security.provider.2=sun.security.rsa.SunRsaSign -security.provider.3=sun.security.ec.SunEC -security.provider.4=com.sun.net.ssl.internal.ssl.Provider -security.provider.5=com.sun.crypto.provider.SunJCE -security.provider.6=sun.security.jgss.SunProvider -security.provider.7=com.sun.security.sasl.Provider -security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI -security.provider.9=sun.security.smartcardio.SunPCSC - -# -# Sun Provider SecureRandom seed source. -# -# Select the primary source of seed data for the "SHA1PRNG" and -# "NativePRNG" SecureRandom implementations in the "Sun" provider. -# (Other SecureRandom implementations might also use this property.) -# -# On Unix-like systems (for example, Solaris/Linux/MacOS), the -# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from -# special device files such as file:/dev/random. -# -# On Windows systems, specifying the URLs "file:/dev/random" or -# "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding -# mechanism for SHA1PRNG. -# -# By default, an attempt is made to use the entropy gathering device -# specified by the "securerandom.source" Security property. If an -# exception occurs while accessing the specified URL: -# -# SHA1PRNG: -# the traditional system/thread activity algorithm will be used. -# -# NativePRNG: -# a default value of /dev/random will be used. If neither -# are available, the implementation will be disabled. -# "file" is the only currently supported protocol type. -# -# The entropy gathering device can also be specified with the System -# property "java.security.egd". For example: -# -# % java -Djava.security.egd=file:/dev/random MainClass -# -# Specifying this System property will override the -# "securerandom.source" Security property. -# -# In addition, if "file:/dev/random" or "file:/dev/urandom" is -# specified, the "NativePRNG" implementation will be more preferred than -# SHA1PRNG in the Sun provider. -# -securerandom.source=file:/dev/random - -# -# A list of known strong SecureRandom implementations. -# -# To help guide applications in selecting a suitable strong -# java.security.SecureRandom implementation, Java distributions should -# indicate a list of known strong implementations using the property. -# -# This is a comma-separated list of algorithm and/or algorithm:provider -# entries. -# -securerandom.strongAlgorithms=NativePRNGBlocking:SUN - -# -# Class to instantiate as the javax.security.auth.login.Configuration -# provider. -# -login.configuration.provider=sun.security.provider.ConfigFile - -# -# Default login configuration file -# -#login.config.url.1=file:${user.home}/.java.login.config - -# -# Class to instantiate as the system Policy. This is the name of the class -# that will be used as the Policy object. -# -policy.provider=sun.security.provider.PolicyFile - -# The default is to have a single system-wide policy file, -# and a policy file in the user's home directory. -policy.url.1=file:${java.home}/lib/security/java.policy -policy.url.2=file:${user.home}/.java.policy - -# whether or not we expand properties in the policy file -# if this is set to false, properties (${...}) will not be expanded in policy -# files. -policy.expandProperties=true - -# whether or not we allow an extra policy to be passed on the command line -# with -Djava.security.policy=somefile. Comment out this line to disable -# this feature. -policy.allowSystemProperty=true - -# whether or not we look into the IdentityScope for trusted Identities -# when encountering a 1.1 signed JAR file. If the identity is found -# and is trusted, we grant it AllPermission. -policy.ignoreIdentityScope=false - -# -# Default keystore type. -# -keystore.type=jks - -# -# List of comma-separated packages that start with or equal this string -# will cause a security exception to be thrown when -# passed to checkPackageAccess unless the -# corresponding RuntimePermission ("accessClassInPackage."+package) has -# been granted. -package.access=sun.,\ - com.sun.xml.internal.,\ - com.sun.imageio.,\ - com.sun.istack.internal.,\ - com.sun.jmx.,\ - com.sun.media.sound.,\ - com.sun.naming.internal.,\ - com.sun.proxy.,\ - com.sun.corba.se.,\ - com.sun.org.apache.bcel.internal.,\ - com.sun.org.apache.regexp.internal.,\ - com.sun.org.apache.xerces.internal.,\ - com.sun.org.apache.xpath.internal.,\ - com.sun.org.apache.xalan.internal.extensions.,\ - com.sun.org.apache.xalan.internal.lib.,\ - com.sun.org.apache.xalan.internal.res.,\ - com.sun.org.apache.xalan.internal.templates.,\ - com.sun.org.apache.xalan.internal.utils.,\ - com.sun.org.apache.xalan.internal.xslt.,\ - com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ - com.sun.org.apache.xalan.internal.xsltc.compiler.,\ - com.sun.org.apache.xalan.internal.xsltc.trax.,\ - com.sun.org.apache.xalan.internal.xsltc.util.,\ - com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ - com.sun.org.apache.xml.internal.serializer.utils.,\ - com.sun.org.apache.xml.internal.utils.,\ - com.sun.org.glassfish.,\ - com.oracle.xmlns.internal.,\ - com.oracle.webservices.internal.,\ - org.jcp.xml.dsig.internal.,\ - jdk.internal.,\ - jdk.nashorn.internal.,\ - jdk.nashorn.tools. - - -# -# List of comma-separated packages that start with or equal this string -# will cause a security exception to be thrown when -# passed to checkPackageDefinition unless the -# corresponding RuntimePermission ("defineClassInPackage."+package) has -# been granted. -# -# by default, none of the class loaders supplied with the JDK call -# checkPackageDefinition. -# -package.definition=sun.,\ - com.sun.xml.internal.,\ - com.sun.imageio.,\ - com.sun.istack.internal.,\ - com.sun.jmx.,\ - com.sun.media.sound.,\ - com.sun.naming.internal.,\ - com.sun.proxy.,\ - com.sun.corba.se.,\ - com.sun.org.apache.bcel.internal.,\ - com.sun.org.apache.regexp.internal.,\ - com.sun.org.apache.xerces.internal.,\ - com.sun.org.apache.xpath.internal.,\ - com.sun.org.apache.xalan.internal.extensions.,\ - com.sun.org.apache.xalan.internal.lib.,\ - com.sun.org.apache.xalan.internal.res.,\ - com.sun.org.apache.xalan.internal.templates.,\ - com.sun.org.apache.xalan.internal.utils.,\ - com.sun.org.apache.xalan.internal.xslt.,\ - com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ - com.sun.org.apache.xalan.internal.xsltc.compiler.,\ - com.sun.org.apache.xalan.internal.xsltc.trax.,\ - com.sun.org.apache.xalan.internal.xsltc.util.,\ - com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ - com.sun.org.apache.xml.internal.serializer.utils.,\ - com.sun.org.apache.xml.internal.utils.,\ - com.sun.org.glassfish.,\ - com.oracle.xmlns.internal.,\ - com.oracle.webservices.internal.,\ - org.jcp.xml.dsig.internal.,\ - jdk.internal.,\ - jdk.nashorn.internal.,\ - jdk.nashorn.tools. - - -# -# Determines whether this properties file can be appended to -# or overridden on the command line via -Djava.security.properties -# -security.overridePropertiesFile=true - -# -# Determines the default key and trust manager factory algorithms for -# the javax.net.ssl package. -# -ssl.KeyManagerFactory.algorithm=SunX509 -ssl.TrustManagerFactory.algorithm=PKIX - -# -# The Java-level namelookup cache policy for successful lookups: -# -# any negative value: caching forever -# any positive value: the number of seconds to cache an address for -# zero: do not cache -# -# default value is forever (FOREVER). For security reasons, this -# caching is made forever when a security manager is set. When a security -# manager is not set, the default behavior in this implementation -# is to cache for 30 seconds. -# -# NOTE: setting this to anything other than the default value can have -# serious security implications. Do not set it unless -# you are sure you are not exposed to DNS spoofing attack. -# -#networkaddress.cache.ttl=-1 - -# The Java-level namelookup cache policy for failed lookups: -# -# any negative value: cache forever -# any positive value: the number of seconds to cache negative lookup results -# zero: do not cache -# -# In some Microsoft Windows networking environments that employ -# the WINS name service in addition to DNS, name service lookups -# that fail may take a noticeably long time to return (approx. 5 seconds). -# For this reason the default caching policy is to maintain these -# results for 10 seconds. -# -# -networkaddress.cache.negative.ttl=10 - -# -# Properties to configure OCSP for certificate revocation checking -# - -# Enable OCSP -# -# By default, OCSP is not used for certificate revocation checking. -# This property enables the use of OCSP when set to the value "true". -# -# NOTE: SocketPermission is required to connect to an OCSP responder. -# -# Example, -# ocsp.enable=true - -# -# Location of the OCSP responder -# -# By default, the location of the OCSP responder is determined implicitly -# from the certificate being validated. This property explicitly specifies -# the location of the OCSP responder. The property is used when the -# Authority Information Access extension (defined in RFC 3280) is absent -# from the certificate or when it requires overriding. -# -# Example, -# ocsp.responderURL=http://ocsp.example.net:80 - -# -# Subject name of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. In cases where -# the subject name alone is not sufficient to uniquely identify the certificate -# then both the "ocsp.responderCertIssuerName" and -# "ocsp.responderCertSerialNumber" properties must be used instead. When this -# property is set then those two properties are ignored. -# -# Example, -# ocsp.responderCertSubjectName="CN=OCSP Responder, O=XYZ Corp" - -# -# Issuer name of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. When this -# property is set then the "ocsp.responderCertSerialNumber" property must also -# be set. When the "ocsp.responderCertSubjectName" property is set then this -# property is ignored. -# -# Example, -# ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp" - -# -# Serial number of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# of hexadecimal digits (colon or space separators may be present) which -# identifies a certificate in the set of certificates supplied during cert path -# validation. When this property is set then the "ocsp.responderCertIssuerName" -# property must also be set. When the "ocsp.responderCertSubjectName" property -# is set then this property is ignored. -# -# Example, -# ocsp.responderCertSerialNumber=2A:FF:00 - -# -# Policy for failed Kerberos KDC lookups: -# -# When a KDC is unavailable (network error, service failure, etc), it is -# put inside a blacklist and accessed less often for future requests. The -# value (case-insensitive) for this policy can be: -# -# tryLast -# KDCs in the blacklist are always tried after those not on the list. -# -# tryLess[:max_retries,timeout] -# KDCs in the blacklist are still tried by their order in the configuration, -# but with smaller max_retries and timeout values. max_retries and timeout -# are optional numerical parameters (default 1 and 5000, which means once -# and 5 seconds). Please notes that if any of the values defined here is -# more than what is defined in krb5.conf, it will be ignored. -# -# Whenever a KDC is detected as available, it is removed from the blacklist. -# The blacklist is reset when krb5.conf is reloaded. You can add -# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is -# reloaded whenever a JAAS authentication is attempted. -# -# Example, -# krb5.kdc.bad.policy = tryLast -# krb5.kdc.bad.policy = tryLess:2,2000 -krb5.kdc.bad.policy = tryLast - -# Algorithm restrictions for certification path (CertPath) processing -# -# In some environments, certain algorithms or key lengths may be undesirable -# for certification path building and validation. For example, "MD2" is -# generally no longer considered to be a secure hash algorithm. This section -# describes the mechanism for disabling algorithms based on algorithm name -# and/or key length. This includes algorithms used in certificates, as well -# as revocation information such as CRLs and signed OCSP Responses. -# -# The syntax of the disabled algorithm string is described as this Java -# BNF-style: -# DisabledAlgorithms: -# " DisabledAlgorithm { , DisabledAlgorithm } " -# -# DisabledAlgorithm: -# AlgorithmName [Constraint] -# -# AlgorithmName: -# (see below) -# -# Constraint: -# KeySizeConstraint -# -# KeySizeConstraint: -# keySize Operator DecimalInteger -# -# Operator: -# <= | < | == | != | >= | > -# -# DecimalInteger: -# DecimalDigits -# -# DecimalDigits: -# DecimalDigit {DecimalDigit} -# -# DecimalDigit: one of -# 1 2 3 4 5 6 7 8 9 0 -# -# The "AlgorithmName" is the standard algorithm name of the disabled -# algorithm. See "Java Cryptography Architecture Standard Algorithm Name -# Documentation" for information about Standard Algorithm Names. Matching -# is performed using a case-insensitive sub-element matching rule. (For -# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and -# "ECDSA" for signatures.) If the assertion "AlgorithmName" is a -# sub-element of the certificate algorithm name, the algorithm will be -# rejected during certification path building and validation. For example, -# the assertion algorithm name "DSA" will disable all certificate algorithms -# that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion -# will not disable algorithms related to "ECDSA". -# -# A "Constraint" provides further guidance for the algorithm being specified. -# The "KeySizeConstraint" requires a key of a valid size range if the -# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the -# key size specified in number of bits. For example, "RSA keySize <= 1024" -# indicates that any RSA key with key size less than or equal to 1024 bits -# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates -# that any RSA key with key size less than 1024 or greater than 2048 should -# be disabled. Note that the "KeySizeConstraint" only makes sense to key -# algorithms. -# -# Note: This property is currently used by Oracle's PKIX implementation. It -# is not guaranteed to be examined and used by other implementations. -# -# Example: -# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 -# -# -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 - -# Algorithm restrictions for Secure Socket Layer/Transport Layer Security -# (SSL/TLS) processing -# -# In some environments, certain algorithms or key lengths may be undesirable -# when using SSL/TLS. This section describes the mechanism for disabling -# algorithms during SSL/TLS security parameters negotiation, including cipher -# suites selection, peer authentication and key exchange mechanisms. -# -# For PKI-based peer authentication and key exchange mechanisms, this list -# of disabled algorithms will also be checked during certification path -# building and validation, including algorithms used in certificates, as -# well as revocation information such as CRLs and signed OCSP Responses. -# This is in addition to the jdk.certpath.disabledAlgorithms property above. -# -# See the specification of "jdk.certpath.disabledAlgorithms" for the -# syntax of the disabled algorithm string. -# -# Note: This property is currently used by Oracle's JSSE implementation. -# It is not guaranteed to be examined and used by other implementations. -# -# Example: -# jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048 diff --git a/jdk/src/java.base/share/conf/security/java.security-linux b/jdk/src/java.base/share/conf/security/java.security-linux deleted file mode 100644 index 6f4204cf791..00000000000 --- a/jdk/src/java.base/share/conf/security/java.security-linux +++ /dev/null @@ -1,496 +0,0 @@ -# -# This is the "master security properties file". -# -# An alternate java.security properties file may be specified -# from the command line via the system property -# -# -Djava.security.properties= -# -# This properties file appends to the master security properties file. -# If both properties files specify values for the same key, the value -# from the command-line properties file is selected, as it is the last -# one loaded. -# -# Also, if you specify -# -# -Djava.security.properties== (2 equals), -# -# then that properties file completely overrides the master security -# properties file. -# -# To disable the ability to specify an additional properties file from -# the command line, set the key security.overridePropertiesFile -# to false in the master security properties file. It is set to true -# by default. - -# In this file, various security properties are set for use by -# java.security classes. This is where users can statically register -# Cryptography Package Providers ("providers" for short). The term -# "provider" refers to a package or set of packages that supply a -# concrete implementation of a subset of the cryptography aspects of -# the Java Security API. A provider may, for example, implement one or -# more digital signature algorithms or message digest algorithms. -# -# Each provider must implement a subclass of the Provider class. -# To register a provider in this master security properties file, -# specify the Provider subclass name and priority in the format -# -# security.provider.= -# -# This declares a provider, and specifies its preference -# order n. The preference order is the order in which providers are -# searched for requested algorithms (when no specific provider is -# requested). The order is 1-based; 1 is the most preferred, followed -# by 2, and so on. -# -# must specify the subclass of the Provider class whose -# constructor sets the values of various properties that are required -# for the Java Security API to look up the algorithms or other -# facilities implemented by the provider. -# -# There must be at least one provider specification in java.security. -# There is a default provider that comes standard with the JDK. It -# is called the "SUN" provider, and its Provider subclass -# named Sun appears in the sun.security.provider package. Thus, the -# "SUN" provider is registered via the following: -# -# security.provider.1=sun.security.provider.Sun -# -# (The number 1 is used for the default provider.) -# -# Note: Providers can be dynamically registered instead by calls to -# either the addProvider or insertProviderAt method in the Security -# class. - -# -# List of providers and their preference orders (see above): -# -security.provider.1=sun.security.provider.Sun -security.provider.2=sun.security.rsa.SunRsaSign -security.provider.3=sun.security.ec.SunEC -security.provider.4=com.sun.net.ssl.internal.ssl.Provider -security.provider.5=com.sun.crypto.provider.SunJCE -security.provider.6=sun.security.jgss.SunProvider -security.provider.7=com.sun.security.sasl.Provider -security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI -security.provider.9=sun.security.smartcardio.SunPCSC - -# -# Sun Provider SecureRandom seed source. -# -# Select the primary source of seed data for the "SHA1PRNG" and -# "NativePRNG" SecureRandom implementations in the "Sun" provider. -# (Other SecureRandom implementations might also use this property.) -# -# On Unix-like systems (for example, Solaris/Linux/MacOS), the -# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from -# special device files such as file:/dev/random. -# -# On Windows systems, specifying the URLs "file:/dev/random" or -# "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding -# mechanism for SHA1PRNG. -# -# By default, an attempt is made to use the entropy gathering device -# specified by the "securerandom.source" Security property. If an -# exception occurs while accessing the specified URL: -# -# SHA1PRNG: -# the traditional system/thread activity algorithm will be used. -# -# NativePRNG: -# a default value of /dev/random will be used. If neither -# are available, the implementation will be disabled. -# "file" is the only currently supported protocol type. -# -# The entropy gathering device can also be specified with the System -# property "java.security.egd". For example: -# -# % java -Djava.security.egd=file:/dev/random MainClass -# -# Specifying this System property will override the -# "securerandom.source" Security property. -# -# In addition, if "file:/dev/random" or "file:/dev/urandom" is -# specified, the "NativePRNG" implementation will be more preferred than -# SHA1PRNG in the Sun provider. -# -securerandom.source=file:/dev/random - -# -# A list of known strong SecureRandom implementations. -# -# To help guide applications in selecting a suitable strong -# java.security.SecureRandom implementation, Java distributions should -# indicate a list of known strong implementations using the property. -# -# This is a comma-separated list of algorithm and/or algorithm:provider -# entries. -# -securerandom.strongAlgorithms=NativePRNGBlocking:SUN - -# -# Class to instantiate as the javax.security.auth.login.Configuration -# provider. -# -login.configuration.provider=sun.security.provider.ConfigFile - -# -# Default login configuration file -# -#login.config.url.1=file:${user.home}/.java.login.config - -# -# Class to instantiate as the system Policy. This is the name of the class -# that will be used as the Policy object. -# -policy.provider=sun.security.provider.PolicyFile - -# The default is to have a single system-wide policy file, -# and a policy file in the user's home directory. -policy.url.1=file:${java.home}/lib/security/java.policy -policy.url.2=file:${user.home}/.java.policy - -# whether or not we expand properties in the policy file -# if this is set to false, properties (${...}) will not be expanded in policy -# files. -policy.expandProperties=true - -# whether or not we allow an extra policy to be passed on the command line -# with -Djava.security.policy=somefile. Comment out this line to disable -# this feature. -policy.allowSystemProperty=true - -# whether or not we look into the IdentityScope for trusted Identities -# when encountering a 1.1 signed JAR file. If the identity is found -# and is trusted, we grant it AllPermission. -policy.ignoreIdentityScope=false - -# -# Default keystore type. -# -keystore.type=jks - -# -# List of comma-separated packages that start with or equal this string -# will cause a security exception to be thrown when -# passed to checkPackageAccess unless the -# corresponding RuntimePermission ("accessClassInPackage."+package) has -# been granted. -package.access=sun.,\ - com.sun.xml.internal.,\ - com.sun.imageio.,\ - com.sun.istack.internal.,\ - com.sun.jmx.,\ - com.sun.media.sound.,\ - com.sun.naming.internal.,\ - com.sun.proxy.,\ - com.sun.corba.se.,\ - com.sun.org.apache.bcel.internal.,\ - com.sun.org.apache.regexp.internal.,\ - com.sun.org.apache.xerces.internal.,\ - com.sun.org.apache.xpath.internal.,\ - com.sun.org.apache.xalan.internal.extensions.,\ - com.sun.org.apache.xalan.internal.lib.,\ - com.sun.org.apache.xalan.internal.res.,\ - com.sun.org.apache.xalan.internal.templates.,\ - com.sun.org.apache.xalan.internal.utils.,\ - com.sun.org.apache.xalan.internal.xslt.,\ - com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ - com.sun.org.apache.xalan.internal.xsltc.compiler.,\ - com.sun.org.apache.xalan.internal.xsltc.trax.,\ - com.sun.org.apache.xalan.internal.xsltc.util.,\ - com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ - com.sun.org.apache.xml.internal.serializer.utils.,\ - com.sun.org.apache.xml.internal.utils.,\ - com.sun.org.glassfish.,\ - com.oracle.xmlns.internal.,\ - com.oracle.webservices.internal.,\ - org.jcp.xml.dsig.internal.,\ - jdk.internal.,\ - jdk.nashorn.internal.,\ - jdk.nashorn.tools.,\ - com.sun.activation.registries. - -# -# List of comma-separated packages that start with or equal this string -# will cause a security exception to be thrown when -# passed to checkPackageDefinition unless the -# corresponding RuntimePermission ("defineClassInPackage."+package) has -# been granted. -# -# by default, none of the class loaders supplied with the JDK call -# checkPackageDefinition. -# -package.definition=sun.,\ - com.sun.xml.internal.,\ - com.sun.imageio.,\ - com.sun.istack.internal.,\ - com.sun.jmx.,\ - com.sun.media.sound.,\ - com.sun.naming.internal.,\ - com.sun.proxy.,\ - com.sun.corba.se.,\ - com.sun.org.apache.bcel.internal.,\ - com.sun.org.apache.regexp.internal.,\ - com.sun.org.apache.xerces.internal.,\ - com.sun.org.apache.xpath.internal.,\ - com.sun.org.apache.xalan.internal.extensions.,\ - com.sun.org.apache.xalan.internal.lib.,\ - com.sun.org.apache.xalan.internal.res.,\ - com.sun.org.apache.xalan.internal.templates.,\ - com.sun.org.apache.xalan.internal.utils.,\ - com.sun.org.apache.xalan.internal.xslt.,\ - com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ - com.sun.org.apache.xalan.internal.xsltc.compiler.,\ - com.sun.org.apache.xalan.internal.xsltc.trax.,\ - com.sun.org.apache.xalan.internal.xsltc.util.,\ - com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ - com.sun.org.apache.xml.internal.serializer.utils.,\ - com.sun.org.apache.xml.internal.utils.,\ - com.sun.org.glassfish.,\ - com.oracle.xmlns.internal.,\ - com.oracle.webservices.internal.,\ - org.jcp.xml.dsig.internal.,\ - jdk.internal.,\ - jdk.nashorn.internal.,\ - jdk.nashorn.tools.,\ - com.sun.activation.registries. - -# -# Determines whether this properties file can be appended to -# or overridden on the command line via -Djava.security.properties -# -security.overridePropertiesFile=true - -# -# Determines the default key and trust manager factory algorithms for -# the javax.net.ssl package. -# -ssl.KeyManagerFactory.algorithm=SunX509 -ssl.TrustManagerFactory.algorithm=PKIX - -# -# The Java-level namelookup cache policy for successful lookups: -# -# any negative value: caching forever -# any positive value: the number of seconds to cache an address for -# zero: do not cache -# -# default value is forever (FOREVER). For security reasons, this -# caching is made forever when a security manager is set. When a security -# manager is not set, the default behavior in this implementation -# is to cache for 30 seconds. -# -# NOTE: setting this to anything other than the default value can have -# serious security implications. Do not set it unless -# you are sure you are not exposed to DNS spoofing attack. -# -#networkaddress.cache.ttl=-1 - -# The Java-level namelookup cache policy for failed lookups: -# -# any negative value: cache forever -# any positive value: the number of seconds to cache negative lookup results -# zero: do not cache -# -# In some Microsoft Windows networking environments that employ -# the WINS name service in addition to DNS, name service lookups -# that fail may take a noticeably long time to return (approx. 5 seconds). -# For this reason the default caching policy is to maintain these -# results for 10 seconds. -# -# -networkaddress.cache.negative.ttl=10 - -# -# Properties to configure OCSP for certificate revocation checking -# - -# Enable OCSP -# -# By default, OCSP is not used for certificate revocation checking. -# This property enables the use of OCSP when set to the value "true". -# -# NOTE: SocketPermission is required to connect to an OCSP responder. -# -# Example, -# ocsp.enable=true - -# -# Location of the OCSP responder -# -# By default, the location of the OCSP responder is determined implicitly -# from the certificate being validated. This property explicitly specifies -# the location of the OCSP responder. The property is used when the -# Authority Information Access extension (defined in RFC 3280) is absent -# from the certificate or when it requires overriding. -# -# Example, -# ocsp.responderURL=http://ocsp.example.net:80 - -# -# Subject name of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. In cases where -# the subject name alone is not sufficient to uniquely identify the certificate -# then both the "ocsp.responderCertIssuerName" and -# "ocsp.responderCertSerialNumber" properties must be used instead. When this -# property is set then those two properties are ignored. -# -# Example, -# ocsp.responderCertSubjectName="CN=OCSP Responder, O=XYZ Corp" - -# -# Issuer name of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. When this -# property is set then the "ocsp.responderCertSerialNumber" property must also -# be set. When the "ocsp.responderCertSubjectName" property is set then this -# property is ignored. -# -# Example, -# ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp" - -# -# Serial number of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# of hexadecimal digits (colon or space separators may be present) which -# identifies a certificate in the set of certificates supplied during cert path -# validation. When this property is set then the "ocsp.responderCertIssuerName" -# property must also be set. When the "ocsp.responderCertSubjectName" property -# is set then this property is ignored. -# -# Example, -# ocsp.responderCertSerialNumber=2A:FF:00 - -# -# Policy for failed Kerberos KDC lookups: -# -# When a KDC is unavailable (network error, service failure, etc), it is -# put inside a blacklist and accessed less often for future requests. The -# value (case-insensitive) for this policy can be: -# -# tryLast -# KDCs in the blacklist are always tried after those not on the list. -# -# tryLess[:max_retries,timeout] -# KDCs in the blacklist are still tried by their order in the configuration, -# but with smaller max_retries and timeout values. max_retries and timeout -# are optional numerical parameters (default 1 and 5000, which means once -# and 5 seconds). Please notes that if any of the values defined here is -# more than what is defined in krb5.conf, it will be ignored. -# -# Whenever a KDC is detected as available, it is removed from the blacklist. -# The blacklist is reset when krb5.conf is reloaded. You can add -# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is -# reloaded whenever a JAAS authentication is attempted. -# -# Example, -# krb5.kdc.bad.policy = tryLast -# krb5.kdc.bad.policy = tryLess:2,2000 -krb5.kdc.bad.policy = tryLast - -# Algorithm restrictions for certification path (CertPath) processing -# -# In some environments, certain algorithms or key lengths may be undesirable -# for certification path building and validation. For example, "MD2" is -# generally no longer considered to be a secure hash algorithm. This section -# describes the mechanism for disabling algorithms based on algorithm name -# and/or key length. This includes algorithms used in certificates, as well -# as revocation information such as CRLs and signed OCSP Responses. -# -# The syntax of the disabled algorithm string is described as this Java -# BNF-style: -# DisabledAlgorithms: -# " DisabledAlgorithm { , DisabledAlgorithm } " -# -# DisabledAlgorithm: -# AlgorithmName [Constraint] -# -# AlgorithmName: -# (see below) -# -# Constraint: -# KeySizeConstraint -# -# KeySizeConstraint: -# keySize Operator DecimalInteger -# -# Operator: -# <= | < | == | != | >= | > -# -# DecimalInteger: -# DecimalDigits -# -# DecimalDigits: -# DecimalDigit {DecimalDigit} -# -# DecimalDigit: one of -# 1 2 3 4 5 6 7 8 9 0 -# -# The "AlgorithmName" is the standard algorithm name of the disabled -# algorithm. See "Java Cryptography Architecture Standard Algorithm Name -# Documentation" for information about Standard Algorithm Names. Matching -# is performed using a case-insensitive sub-element matching rule. (For -# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and -# "ECDSA" for signatures.) If the assertion "AlgorithmName" is a -# sub-element of the certificate algorithm name, the algorithm will be -# rejected during certification path building and validation. For example, -# the assertion algorithm name "DSA" will disable all certificate algorithms -# that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion -# will not disable algorithms related to "ECDSA". -# -# A "Constraint" provides further guidance for the algorithm being specified. -# The "KeySizeConstraint" requires a key of a valid size range if the -# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the -# key size specified in number of bits. For example, "RSA keySize <= 1024" -# indicates that any RSA key with key size less than or equal to 1024 bits -# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates -# that any RSA key with key size less than 1024 or greater than 2048 should -# be disabled. Note that the "KeySizeConstraint" only makes sense to key -# algorithms. -# -# Note: This property is currently used by Oracle's PKIX implementation. It -# is not guaranteed to be examined and used by other implementations. -# -# Example: -# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 -# -# -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 - -# Algorithm restrictions for Secure Socket Layer/Transport Layer Security -# (SSL/TLS) processing -# -# In some environments, certain algorithms or key lengths may be undesirable -# when using SSL/TLS. This section describes the mechanism for disabling -# algorithms during SSL/TLS security parameters negotiation, including cipher -# suites selection, peer authentication and key exchange mechanisms. -# -# For PKI-based peer authentication and key exchange mechanisms, this list -# of disabled algorithms will also be checked during certification path -# building and validation, including algorithms used in certificates, as -# well as revocation information such as CRLs and signed OCSP Responses. -# This is in addition to the jdk.certpath.disabledAlgorithms property above. -# -# See the specification of "jdk.certpath.disabledAlgorithms" for the -# syntax of the disabled algorithm string. -# -# Note: This property is currently used by Oracle's JSSE implementation. -# It is not guaranteed to be examined and used by other implementations. -# -# Example: -# jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048 diff --git a/jdk/src/java.base/share/conf/security/java.security-macosx b/jdk/src/java.base/share/conf/security/java.security-macosx deleted file mode 100644 index ff726991c56..00000000000 --- a/jdk/src/java.base/share/conf/security/java.security-macosx +++ /dev/null @@ -1,499 +0,0 @@ -# -# This is the "master security properties file". -# -# An alternate java.security properties file may be specified -# from the command line via the system property -# -# -Djava.security.properties= -# -# This properties file appends to the master security properties file. -# If both properties files specify values for the same key, the value -# from the command-line properties file is selected, as it is the last -# one loaded. -# -# Also, if you specify -# -# -Djava.security.properties== (2 equals), -# -# then that properties file completely overrides the master security -# properties file. -# -# To disable the ability to specify an additional properties file from -# the command line, set the key security.overridePropertiesFile -# to false in the master security properties file. It is set to true -# by default. - -# In this file, various security properties are set for use by -# java.security classes. This is where users can statically register -# Cryptography Package Providers ("providers" for short). The term -# "provider" refers to a package or set of packages that supply a -# concrete implementation of a subset of the cryptography aspects of -# the Java Security API. A provider may, for example, implement one or -# more digital signature algorithms or message digest algorithms. -# -# Each provider must implement a subclass of the Provider class. -# To register a provider in this master security properties file, -# specify the Provider subclass name and priority in the format -# -# security.provider.= -# -# This declares a provider, and specifies its preference -# order n. The preference order is the order in which providers are -# searched for requested algorithms (when no specific provider is -# requested). The order is 1-based; 1 is the most preferred, followed -# by 2, and so on. -# -# must specify the subclass of the Provider class whose -# constructor sets the values of various properties that are required -# for the Java Security API to look up the algorithms or other -# facilities implemented by the provider. -# -# There must be at least one provider specification in java.security. -# There is a default provider that comes standard with the JDK. It -# is called the "SUN" provider, and its Provider subclass -# named Sun appears in the sun.security.provider package. Thus, the -# "SUN" provider is registered via the following: -# -# security.provider.1=sun.security.provider.Sun -# -# (The number 1 is used for the default provider.) -# -# Note: Providers can be dynamically registered instead by calls to -# either the addProvider or insertProviderAt method in the Security -# class. - -# -# List of providers and their preference orders (see above): -# -security.provider.1=sun.security.provider.Sun -security.provider.2=sun.security.rsa.SunRsaSign -security.provider.3=sun.security.ec.SunEC -security.provider.4=com.sun.net.ssl.internal.ssl.Provider -security.provider.5=com.sun.crypto.provider.SunJCE -security.provider.6=sun.security.jgss.SunProvider -security.provider.7=com.sun.security.sasl.Provider -security.provider.8=org.jcp.xml.dsig.internal.dom.XMLDSigRI -security.provider.9=sun.security.smartcardio.SunPCSC -security.provider.10=apple.security.AppleProvider - -# -# Sun Provider SecureRandom seed source. -# -# Select the primary source of seed data for the "SHA1PRNG" and -# "NativePRNG" SecureRandom implementations in the "Sun" provider. -# (Other SecureRandom implementations might also use this property.) -# -# On Unix-like systems (for example, Solaris/Linux/MacOS), the -# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from -# special device files such as file:/dev/random. -# -# On Windows systems, specifying the URLs "file:/dev/random" or -# "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding -# mechanism for SHA1PRNG. -# -# By default, an attempt is made to use the entropy gathering device -# specified by the "securerandom.source" Security property. If an -# exception occurs while accessing the specified URL: -# -# SHA1PRNG: -# the traditional system/thread activity algorithm will be used. -# -# NativePRNG: -# a default value of /dev/random will be used. If neither -# are available, the implementation will be disabled. -# "file" is the only currently supported protocol type. -# -# The entropy gathering device can also be specified with the System -# property "java.security.egd". For example: -# -# % java -Djava.security.egd=file:/dev/random MainClass -# -# Specifying this System property will override the -# "securerandom.source" Security property. -# -# In addition, if "file:/dev/random" or "file:/dev/urandom" is -# specified, the "NativePRNG" implementation will be more preferred than -# SHA1PRNG in the Sun provider. -# -securerandom.source=file:/dev/random - -# -# A list of known strong SecureRandom implementations. -# -# To help guide applications in selecting a suitable strong -# java.security.SecureRandom implementation, Java distributions should -# indicate a list of known strong implementations using the property. -# -# This is a comma-separated list of algorithm and/or algorithm:provider -# entries. -# -securerandom.strongAlgorithms=NativePRNGBlocking:SUN - -# -# Class to instantiate as the javax.security.auth.login.Configuration -# provider. -# -login.configuration.provider=sun.security.provider.ConfigFile - -# -# Default login configuration file -# -#login.config.url.1=file:${user.home}/.java.login.config - -# -# Class to instantiate as the system Policy. This is the name of the class -# that will be used as the Policy object. -# -policy.provider=sun.security.provider.PolicyFile - -# The default is to have a single system-wide policy file, -# and a policy file in the user's home directory. -policy.url.1=file:${java.home}/lib/security/java.policy -policy.url.2=file:${user.home}/.java.policy - -# whether or not we expand properties in the policy file -# if this is set to false, properties (${...}) will not be expanded in policy -# files. -policy.expandProperties=true - -# whether or not we allow an extra policy to be passed on the command line -# with -Djava.security.policy=somefile. Comment out this line to disable -# this feature. -policy.allowSystemProperty=true - -# whether or not we look into the IdentityScope for trusted Identities -# when encountering a 1.1 signed JAR file. If the identity is found -# and is trusted, we grant it AllPermission. -policy.ignoreIdentityScope=false - -# -# Default keystore type. -# -keystore.type=jks - -# -# List of comma-separated packages that start with or equal this string -# will cause a security exception to be thrown when -# passed to checkPackageAccess unless the -# corresponding RuntimePermission ("accessClassInPackage."+package) has -# been granted. -package.access=sun.,\ - com.sun.xml.internal.,\ - com.sun.imageio.,\ - com.sun.istack.internal.,\ - com.sun.jmx.,\ - com.sun.media.sound.,\ - com.sun.naming.internal.,\ - com.sun.proxy.,\ - com.sun.corba.se.,\ - com.sun.org.apache.bcel.internal.,\ - com.sun.org.apache.regexp.internal.,\ - com.sun.org.apache.xerces.internal.,\ - com.sun.org.apache.xpath.internal.,\ - com.sun.org.apache.xalan.internal.extensions.,\ - com.sun.org.apache.xalan.internal.lib.,\ - com.sun.org.apache.xalan.internal.res.,\ - com.sun.org.apache.xalan.internal.templates.,\ - com.sun.org.apache.xalan.internal.utils.,\ - com.sun.org.apache.xalan.internal.xslt.,\ - com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ - com.sun.org.apache.xalan.internal.xsltc.compiler.,\ - com.sun.org.apache.xalan.internal.xsltc.trax.,\ - com.sun.org.apache.xalan.internal.xsltc.util.,\ - com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ - com.sun.org.apache.xml.internal.serializer.utils.,\ - com.sun.org.apache.xml.internal.utils.,\ - com.sun.org.glassfish.,\ - com.oracle.xmlns.internal.,\ - com.oracle.webservices.internal.,\ - org.jcp.xml.dsig.internal.,\ - jdk.internal.,\ - jdk.nashorn.internal.,\ - jdk.nashorn.tools.,\ - com.sun.activation.registries.,\ - apple. - -# -# List of comma-separated packages that start with or equal this string -# will cause a security exception to be thrown when -# passed to checkPackageDefinition unless the -# corresponding RuntimePermission ("defineClassInPackage."+package) has -# been granted. -# -# by default, none of the class loaders supplied with the JDK call -# checkPackageDefinition. -# -package.definition=sun.,\ - com.sun.xml.internal.,\ - com.sun.imageio.,\ - com.sun.istack.internal.,\ - com.sun.jmx.,\ - com.sun.media.sound.,\ - com.sun.naming.internal.,\ - com.sun.proxy.,\ - com.sun.corba.se.,\ - com.sun.org.apache.bcel.internal.,\ - com.sun.org.apache.regexp.internal.,\ - com.sun.org.apache.xerces.internal.,\ - com.sun.org.apache.xpath.internal.,\ - com.sun.org.apache.xalan.internal.extensions.,\ - com.sun.org.apache.xalan.internal.lib.,\ - com.sun.org.apache.xalan.internal.res.,\ - com.sun.org.apache.xalan.internal.templates.,\ - com.sun.org.apache.xalan.internal.utils.,\ - com.sun.org.apache.xalan.internal.xslt.,\ - com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ - com.sun.org.apache.xalan.internal.xsltc.compiler.,\ - com.sun.org.apache.xalan.internal.xsltc.trax.,\ - com.sun.org.apache.xalan.internal.xsltc.util.,\ - com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ - com.sun.org.apache.xml.internal.serializer.utils.,\ - com.sun.org.apache.xml.internal.utils.,\ - com.sun.org.glassfish.,\ - com.oracle.xmlns.internal.,\ - com.oracle.webservices.internal.,\ - org.jcp.xml.dsig.internal.,\ - jdk.internal.,\ - jdk.nashorn.internal.,\ - jdk.nashorn.tools.,\ - com.sun.activation.registries.,\ - apple. - -# -# Determines whether this properties file can be appended to -# or overridden on the command line via -Djava.security.properties -# -security.overridePropertiesFile=true - -# -# Determines the default key and trust manager factory algorithms for -# the javax.net.ssl package. -# -ssl.KeyManagerFactory.algorithm=SunX509 -ssl.TrustManagerFactory.algorithm=PKIX - -# -# The Java-level namelookup cache policy for successful lookups: -# -# any negative value: caching forever -# any positive value: the number of seconds to cache an address for -# zero: do not cache -# -# default value is forever (FOREVER). For security reasons, this -# caching is made forever when a security manager is set. When a security -# manager is not set, the default behavior in this implementation -# is to cache for 30 seconds. -# -# NOTE: setting this to anything other than the default value can have -# serious security implications. Do not set it unless -# you are sure you are not exposed to DNS spoofing attack. -# -#networkaddress.cache.ttl=-1 - -# The Java-level namelookup cache policy for failed lookups: -# -# any negative value: cache forever -# any positive value: the number of seconds to cache negative lookup results -# zero: do not cache -# -# In some Microsoft Windows networking environments that employ -# the WINS name service in addition to DNS, name service lookups -# that fail may take a noticeably long time to return (approx. 5 seconds). -# For this reason the default caching policy is to maintain these -# results for 10 seconds. -# -# -networkaddress.cache.negative.ttl=10 - -# -# Properties to configure OCSP for certificate revocation checking -# - -# Enable OCSP -# -# By default, OCSP is not used for certificate revocation checking. -# This property enables the use of OCSP when set to the value "true". -# -# NOTE: SocketPermission is required to connect to an OCSP responder. -# -# Example, -# ocsp.enable=true - -# -# Location of the OCSP responder -# -# By default, the location of the OCSP responder is determined implicitly -# from the certificate being validated. This property explicitly specifies -# the location of the OCSP responder. The property is used when the -# Authority Information Access extension (defined in RFC 3280) is absent -# from the certificate or when it requires overriding. -# -# Example, -# ocsp.responderURL=http://ocsp.example.net:80 - -# -# Subject name of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. In cases where -# the subject name alone is not sufficient to uniquely identify the certificate -# then both the "ocsp.responderCertIssuerName" and -# "ocsp.responderCertSerialNumber" properties must be used instead. When this -# property is set then those two properties are ignored. -# -# Example, -# ocsp.responderCertSubjectName="CN=OCSP Responder, O=XYZ Corp" - -# -# Issuer name of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. When this -# property is set then the "ocsp.responderCertSerialNumber" property must also -# be set. When the "ocsp.responderCertSubjectName" property is set then this -# property is ignored. -# -# Example, -# ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp" - -# -# Serial number of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# of hexadecimal digits (colon or space separators may be present) which -# identifies a certificate in the set of certificates supplied during cert path -# validation. When this property is set then the "ocsp.responderCertIssuerName" -# property must also be set. When the "ocsp.responderCertSubjectName" property -# is set then this property is ignored. -# -# Example, -# ocsp.responderCertSerialNumber=2A:FF:00 - -# -# Policy for failed Kerberos KDC lookups: -# -# When a KDC is unavailable (network error, service failure, etc), it is -# put inside a blacklist and accessed less often for future requests. The -# value (case-insensitive) for this policy can be: -# -# tryLast -# KDCs in the blacklist are always tried after those not on the list. -# -# tryLess[:max_retries,timeout] -# KDCs in the blacklist are still tried by their order in the configuration, -# but with smaller max_retries and timeout values. max_retries and timeout -# are optional numerical parameters (default 1 and 5000, which means once -# and 5 seconds). Please notes that if any of the values defined here is -# more than what is defined in krb5.conf, it will be ignored. -# -# Whenever a KDC is detected as available, it is removed from the blacklist. -# The blacklist is reset when krb5.conf is reloaded. You can add -# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is -# reloaded whenever a JAAS authentication is attempted. -# -# Example, -# krb5.kdc.bad.policy = tryLast -# krb5.kdc.bad.policy = tryLess:2,2000 -krb5.kdc.bad.policy = tryLast - -# Algorithm restrictions for certification path (CertPath) processing -# -# In some environments, certain algorithms or key lengths may be undesirable -# for certification path building and validation. For example, "MD2" is -# generally no longer considered to be a secure hash algorithm. This section -# describes the mechanism for disabling algorithms based on algorithm name -# and/or key length. This includes algorithms used in certificates, as well -# as revocation information such as CRLs and signed OCSP Responses. -# -# The syntax of the disabled algorithm string is described as this Java -# BNF-style: -# DisabledAlgorithms: -# " DisabledAlgorithm { , DisabledAlgorithm } " -# -# DisabledAlgorithm: -# AlgorithmName [Constraint] -# -# AlgorithmName: -# (see below) -# -# Constraint: -# KeySizeConstraint -# -# KeySizeConstraint: -# keySize Operator DecimalInteger -# -# Operator: -# <= | < | == | != | >= | > -# -# DecimalInteger: -# DecimalDigits -# -# DecimalDigits: -# DecimalDigit {DecimalDigit} -# -# DecimalDigit: one of -# 1 2 3 4 5 6 7 8 9 0 -# -# The "AlgorithmName" is the standard algorithm name of the disabled -# algorithm. See "Java Cryptography Architecture Standard Algorithm Name -# Documentation" for information about Standard Algorithm Names. Matching -# is performed using a case-insensitive sub-element matching rule. (For -# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and -# "ECDSA" for signatures.) If the assertion "AlgorithmName" is a -# sub-element of the certificate algorithm name, the algorithm will be -# rejected during certification path building and validation. For example, -# the assertion algorithm name "DSA" will disable all certificate algorithms -# that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion -# will not disable algorithms related to "ECDSA". -# -# A "Constraint" provides further guidance for the algorithm being specified. -# The "KeySizeConstraint" requires a key of a valid size range if the -# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the -# key size specified in number of bits. For example, "RSA keySize <= 1024" -# indicates that any RSA key with key size less than or equal to 1024 bits -# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates -# that any RSA key with key size less than 1024 or greater than 2048 should -# be disabled. Note that the "KeySizeConstraint" only makes sense to key -# algorithms. -# -# Note: This property is currently used by Oracle's PKIX implementation. It -# is not guaranteed to be examined and used by other implementations. -# -# Example: -# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 -# -# -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 - -# Algorithm restrictions for Secure Socket Layer/Transport Layer Security -# (SSL/TLS) processing -# -# In some environments, certain algorithms or key lengths may be undesirable -# when using SSL/TLS. This section describes the mechanism for disabling -# algorithms during SSL/TLS security parameters negotiation, including cipher -# suites selection, peer authentication and key exchange mechanisms. -# -# For PKI-based peer authentication and key exchange mechanisms, this list -# of disabled algorithms will also be checked during certification path -# building and validation, including algorithms used in certificates, as -# well as revocation information such as CRLs and signed OCSP Responses. -# This is in addition to the jdk.certpath.disabledAlgorithms property above. -# -# See the specification of "jdk.certpath.disabledAlgorithms" for the -# syntax of the disabled algorithm string. -# -# Note: This property is currently used by Oracle's JSSE implementation. -# It is not guaranteed to be examined and used by other implementations. -# -# Example: -# jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048 diff --git a/jdk/src/java.base/share/conf/security/java.security-solaris b/jdk/src/java.base/share/conf/security/java.security-solaris deleted file mode 100644 index e26ff143141..00000000000 --- a/jdk/src/java.base/share/conf/security/java.security-solaris +++ /dev/null @@ -1,498 +0,0 @@ -# -# This is the "master security properties file". -# -# An alternate java.security properties file may be specified -# from the command line via the system property -# -# -Djava.security.properties= -# -# This properties file appends to the master security properties file. -# If both properties files specify values for the same key, the value -# from the command-line properties file is selected, as it is the last -# one loaded. -# -# Also, if you specify -# -# -Djava.security.properties== (2 equals), -# -# then that properties file completely overrides the master security -# properties file. -# -# To disable the ability to specify an additional properties file from -# the command line, set the key security.overridePropertiesFile -# to false in the master security properties file. It is set to true -# by default. - -# In this file, various security properties are set for use by -# java.security classes. This is where users can statically register -# Cryptography Package Providers ("providers" for short). The term -# "provider" refers to a package or set of packages that supply a -# concrete implementation of a subset of the cryptography aspects of -# the Java Security API. A provider may, for example, implement one or -# more digital signature algorithms or message digest algorithms. -# -# Each provider must implement a subclass of the Provider class. -# To register a provider in this master security properties file, -# specify the Provider subclass name and priority in the format -# -# security.provider.= -# -# This declares a provider, and specifies its preference -# order n. The preference order is the order in which providers are -# searched for requested algorithms (when no specific provider is -# requested). The order is 1-based; 1 is the most preferred, followed -# by 2, and so on. -# -# must specify the subclass of the Provider class whose -# constructor sets the values of various properties that are required -# for the Java Security API to look up the algorithms or other -# facilities implemented by the provider. -# -# There must be at least one provider specification in java.security. -# There is a default provider that comes standard with the JDK. It -# is called the "SUN" provider, and its Provider subclass -# named Sun appears in the sun.security.provider package. Thus, the -# "SUN" provider is registered via the following: -# -# security.provider.1=sun.security.provider.Sun -# -# (The number 1 is used for the default provider.) -# -# Note: Providers can be dynamically registered instead by calls to -# either the addProvider or insertProviderAt method in the Security -# class. - -# -# List of providers and their preference orders (see above): -# -security.provider.1=com.oracle.security.ucrypto.UcryptoProvider ${java.home}/lib/security/ucrypto-solaris.cfg -security.provider.2=sun.security.pkcs11.SunPKCS11 ${java.home}/lib/security/sunpkcs11-solaris.cfg -security.provider.3=sun.security.provider.Sun -security.provider.4=sun.security.rsa.SunRsaSign -security.provider.5=sun.security.ec.SunEC -security.provider.6=com.sun.net.ssl.internal.ssl.Provider -security.provider.7=com.sun.crypto.provider.SunJCE -security.provider.8=sun.security.jgss.SunProvider -security.provider.9=com.sun.security.sasl.Provider -security.provider.10=org.jcp.xml.dsig.internal.dom.XMLDSigRI -security.provider.11=sun.security.smartcardio.SunPCSC - -# -# Sun Provider SecureRandom seed source. -# -# Select the primary source of seed data for the "SHA1PRNG" and -# "NativePRNG" SecureRandom implementations in the "Sun" provider. -# (Other SecureRandom implementations might also use this property.) -# -# On Unix-like systems (for example, Solaris/Linux/MacOS), the -# "NativePRNG" and "SHA1PRNG" implementations obtains seed data from -# special device files such as file:/dev/random. -# -# On Windows systems, specifying the URLs "file:/dev/random" or -# "file:/dev/urandom" will enable the native Microsoft CryptoAPI seeding -# mechanism for SHA1PRNG. -# -# By default, an attempt is made to use the entropy gathering device -# specified by the "securerandom.source" Security property. If an -# exception occurs while accessing the specified URL: -# -# SHA1PRNG: -# the traditional system/thread activity algorithm will be used. -# -# NativePRNG: -# a default value of /dev/random will be used. If neither -# are available, the implementation will be disabled. -# "file" is the only currently supported protocol type. -# -# The entropy gathering device can also be specified with the System -# property "java.security.egd". For example: -# -# % java -Djava.security.egd=file:/dev/random MainClass -# -# Specifying this System property will override the -# "securerandom.source" Security property. -# -# In addition, if "file:/dev/random" or "file:/dev/urandom" is -# specified, the "NativePRNG" implementation will be more preferred than -# SHA1PRNG in the Sun provider. -# -securerandom.source=file:/dev/random - -# -# A list of known strong SecureRandom implementations. -# -# To help guide applications in selecting a suitable strong -# java.security.SecureRandom implementation, Java distributions should -# indicate a list of known strong implementations using the property. -# -# This is a comma-separated list of algorithm and/or algorithm:provider -# entries. -# -securerandom.strongAlgorithms=NativePRNGBlocking:SUN - -# -# Class to instantiate as the javax.security.auth.login.Configuration -# provider. -# -login.configuration.provider=sun.security.provider.ConfigFile - -# -# Default login configuration file -# -#login.config.url.1=file:${user.home}/.java.login.config - -# -# Class to instantiate as the system Policy. This is the name of the class -# that will be used as the Policy object. -# -policy.provider=sun.security.provider.PolicyFile - -# The default is to have a single system-wide policy file, -# and a policy file in the user's home directory. -policy.url.1=file:${java.home}/lib/security/java.policy -policy.url.2=file:${user.home}/.java.policy - -# whether or not we expand properties in the policy file -# if this is set to false, properties (${...}) will not be expanded in policy -# files. -policy.expandProperties=true - -# whether or not we allow an extra policy to be passed on the command line -# with -Djava.security.policy=somefile. Comment out this line to disable -# this feature. -policy.allowSystemProperty=true - -# whether or not we look into the IdentityScope for trusted Identities -# when encountering a 1.1 signed JAR file. If the identity is found -# and is trusted, we grant it AllPermission. -policy.ignoreIdentityScope=false - -# -# Default keystore type. -# -keystore.type=jks - -# -# List of comma-separated packages that start with or equal this string -# will cause a security exception to be thrown when -# passed to checkPackageAccess unless the -# corresponding RuntimePermission ("accessClassInPackage."+package) has -# been granted. -package.access=sun.,\ - com.sun.xml.internal.,\ - com.sun.imageio.,\ - com.sun.istack.internal.,\ - com.sun.jmx.,\ - com.sun.media.sound.,\ - com.sun.naming.internal.,\ - com.sun.proxy.,\ - com.sun.corba.se.,\ - com.sun.org.apache.bcel.internal.,\ - com.sun.org.apache.regexp.internal.,\ - com.sun.org.apache.xerces.internal.,\ - com.sun.org.apache.xpath.internal.,\ - com.sun.org.apache.xalan.internal.extensions.,\ - com.sun.org.apache.xalan.internal.lib.,\ - com.sun.org.apache.xalan.internal.res.,\ - com.sun.org.apache.xalan.internal.templates.,\ - com.sun.org.apache.xalan.internal.utils.,\ - com.sun.org.apache.xalan.internal.xslt.,\ - com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ - com.sun.org.apache.xalan.internal.xsltc.compiler.,\ - com.sun.org.apache.xalan.internal.xsltc.trax.,\ - com.sun.org.apache.xalan.internal.xsltc.util.,\ - com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ - com.sun.org.apache.xml.internal.serializer.utils.,\ - com.sun.org.apache.xml.internal.utils.,\ - com.sun.org.glassfish.,\ - com.oracle.xmlns.internal.,\ - com.oracle.webservices.internal.,\ - org.jcp.xml.dsig.internal.,\ - jdk.internal.,\ - jdk.nashorn.internal.,\ - jdk.nashorn.tools.,\ - com.sun.activation.registries. - -# -# List of comma-separated packages that start with or equal this string -# will cause a security exception to be thrown when -# passed to checkPackageDefinition unless the -# corresponding RuntimePermission ("defineClassInPackage."+package) has -# been granted. -# -# by default, none of the class loaders supplied with the JDK call -# checkPackageDefinition. -# -package.definition=sun.,\ - com.sun.xml.internal.,\ - com.sun.imageio.,\ - com.sun.istack.internal.,\ - com.sun.jmx.,\ - com.sun.media.sound.,\ - com.sun.naming.internal.,\ - com.sun.proxy.,\ - com.sun.corba.se.,\ - com.sun.org.apache.bcel.internal.,\ - com.sun.org.apache.regexp.internal.,\ - com.sun.org.apache.xerces.internal.,\ - com.sun.org.apache.xpath.internal.,\ - com.sun.org.apache.xalan.internal.extensions.,\ - com.sun.org.apache.xalan.internal.lib.,\ - com.sun.org.apache.xalan.internal.res.,\ - com.sun.org.apache.xalan.internal.templates.,\ - com.sun.org.apache.xalan.internal.utils.,\ - com.sun.org.apache.xalan.internal.xslt.,\ - com.sun.org.apache.xalan.internal.xsltc.cmdline.,\ - com.sun.org.apache.xalan.internal.xsltc.compiler.,\ - com.sun.org.apache.xalan.internal.xsltc.trax.,\ - com.sun.org.apache.xalan.internal.xsltc.util.,\ - com.sun.org.apache.xml.internal.res.,\ - com.sun.org.apache.xml.internal.security.,\ - com.sun.org.apache.xml.internal.serializer.utils.,\ - com.sun.org.apache.xml.internal.utils.,\ - com.sun.org.glassfish.,\ - com.oracle.xmlns.internal.,\ - com.oracle.webservices.internal.,\ - org.jcp.xml.dsig.internal.,\ - jdk.internal.,\ - jdk.nashorn.internal.,\ - jdk.nashorn.tools.,\ - com.sun.activation.registries. - -# -# Determines whether this properties file can be appended to -# or overridden on the command line via -Djava.security.properties -# -security.overridePropertiesFile=true - -# -# Determines the default key and trust manager factory algorithms for -# the javax.net.ssl package. -# -ssl.KeyManagerFactory.algorithm=SunX509 -ssl.TrustManagerFactory.algorithm=PKIX - -# -# The Java-level namelookup cache policy for successful lookups: -# -# any negative value: caching forever -# any positive value: the number of seconds to cache an address for -# zero: do not cache -# -# default value is forever (FOREVER). For security reasons, this -# caching is made forever when a security manager is set. When a security -# manager is not set, the default behavior in this implementation -# is to cache for 30 seconds. -# -# NOTE: setting this to anything other than the default value can have -# serious security implications. Do not set it unless -# you are sure you are not exposed to DNS spoofing attack. -# -#networkaddress.cache.ttl=-1 - -# The Java-level namelookup cache policy for failed lookups: -# -# any negative value: cache forever -# any positive value: the number of seconds to cache negative lookup results -# zero: do not cache -# -# In some Microsoft Windows networking environments that employ -# the WINS name service in addition to DNS, name service lookups -# that fail may take a noticeably long time to return (approx. 5 seconds). -# For this reason the default caching policy is to maintain these -# results for 10 seconds. -# -# -networkaddress.cache.negative.ttl=10 - -# -# Properties to configure OCSP for certificate revocation checking -# - -# Enable OCSP -# -# By default, OCSP is not used for certificate revocation checking. -# This property enables the use of OCSP when set to the value "true". -# -# NOTE: SocketPermission is required to connect to an OCSP responder. -# -# Example, -# ocsp.enable=true - -# -# Location of the OCSP responder -# -# By default, the location of the OCSP responder is determined implicitly -# from the certificate being validated. This property explicitly specifies -# the location of the OCSP responder. The property is used when the -# Authority Information Access extension (defined in RFC 3280) is absent -# from the certificate or when it requires overriding. -# -# Example, -# ocsp.responderURL=http://ocsp.example.net:80 - -# -# Subject name of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. In cases where -# the subject name alone is not sufficient to uniquely identify the certificate -# then both the "ocsp.responderCertIssuerName" and -# "ocsp.responderCertSerialNumber" properties must be used instead. When this -# property is set then those two properties are ignored. -# -# Example, -# ocsp.responderCertSubjectName="CN=OCSP Responder, O=XYZ Corp" - -# -# Issuer name of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# distinguished name (defined in RFC 2253) which identifies a certificate in -# the set of certificates supplied during cert path validation. When this -# property is set then the "ocsp.responderCertSerialNumber" property must also -# be set. When the "ocsp.responderCertSubjectName" property is set then this -# property is ignored. -# -# Example, -# ocsp.responderCertIssuerName="CN=Enterprise CA, O=XYZ Corp" - -# -# Serial number of the OCSP responder's certificate -# -# By default, the certificate of the OCSP responder is that of the issuer -# of the certificate being validated. This property identifies the certificate -# of the OCSP responder when the default does not apply. Its value is a string -# of hexadecimal digits (colon or space separators may be present) which -# identifies a certificate in the set of certificates supplied during cert path -# validation. When this property is set then the "ocsp.responderCertIssuerName" -# property must also be set. When the "ocsp.responderCertSubjectName" property -# is set then this property is ignored. -# -# Example, -# ocsp.responderCertSerialNumber=2A:FF:00 - -# -# Policy for failed Kerberos KDC lookups: -# -# When a KDC is unavailable (network error, service failure, etc), it is -# put inside a blacklist and accessed less often for future requests. The -# value (case-insensitive) for this policy can be: -# -# tryLast -# KDCs in the blacklist are always tried after those not on the list. -# -# tryLess[:max_retries,timeout] -# KDCs in the blacklist are still tried by their order in the configuration, -# but with smaller max_retries and timeout values. max_retries and timeout -# are optional numerical parameters (default 1 and 5000, which means once -# and 5 seconds). Please notes that if any of the values defined here is -# more than what is defined in krb5.conf, it will be ignored. -# -# Whenever a KDC is detected as available, it is removed from the blacklist. -# The blacklist is reset when krb5.conf is reloaded. You can add -# refreshKrb5Config=true to a JAAS configuration file so that krb5.conf is -# reloaded whenever a JAAS authentication is attempted. -# -# Example, -# krb5.kdc.bad.policy = tryLast -# krb5.kdc.bad.policy = tryLess:2,2000 -krb5.kdc.bad.policy = tryLast - -# Algorithm restrictions for certification path (CertPath) processing -# -# In some environments, certain algorithms or key lengths may be undesirable -# for certification path building and validation. For example, "MD2" is -# generally no longer considered to be a secure hash algorithm. This section -# describes the mechanism for disabling algorithms based on algorithm name -# and/or key length. This includes algorithms used in certificates, as well -# as revocation information such as CRLs and signed OCSP Responses. -# -# The syntax of the disabled algorithm string is described as this Java -# BNF-style: -# DisabledAlgorithms: -# " DisabledAlgorithm { , DisabledAlgorithm } " -# -# DisabledAlgorithm: -# AlgorithmName [Constraint] -# -# AlgorithmName: -# (see below) -# -# Constraint: -# KeySizeConstraint -# -# KeySizeConstraint: -# keySize Operator DecimalInteger -# -# Operator: -# <= | < | == | != | >= | > -# -# DecimalInteger: -# DecimalDigits -# -# DecimalDigits: -# DecimalDigit {DecimalDigit} -# -# DecimalDigit: one of -# 1 2 3 4 5 6 7 8 9 0 -# -# The "AlgorithmName" is the standard algorithm name of the disabled -# algorithm. See "Java Cryptography Architecture Standard Algorithm Name -# Documentation" for information about Standard Algorithm Names. Matching -# is performed using a case-insensitive sub-element matching rule. (For -# example, in "SHA1withECDSA" the sub-elements are "SHA1" for hashing and -# "ECDSA" for signatures.) If the assertion "AlgorithmName" is a -# sub-element of the certificate algorithm name, the algorithm will be -# rejected during certification path building and validation. For example, -# the assertion algorithm name "DSA" will disable all certificate algorithms -# that rely on DSA, such as NONEwithDSA, SHA1withDSA. However, the assertion -# will not disable algorithms related to "ECDSA". -# -# A "Constraint" provides further guidance for the algorithm being specified. -# The "KeySizeConstraint" requires a key of a valid size range if the -# "AlgorithmName" is of a key algorithm. The "DecimalInteger" indicates the -# key size specified in number of bits. For example, "RSA keySize <= 1024" -# indicates that any RSA key with key size less than or equal to 1024 bits -# should be disabled, and "RSA keySize < 1024, RSA keySize > 2048" indicates -# that any RSA key with key size less than 1024 or greater than 2048 should -# be disabled. Note that the "KeySizeConstraint" only makes sense to key -# algorithms. -# -# Note: This property is currently used by Oracle's PKIX implementation. It -# is not guaranteed to be examined and used by other implementations. -# -# Example: -# jdk.certpath.disabledAlgorithms=MD2, DSA, RSA keySize < 2048 -# -# -jdk.certpath.disabledAlgorithms=MD2, MD5, RSA keySize < 1024 - -# Algorithm restrictions for Secure Socket Layer/Transport Layer Security -# (SSL/TLS) processing -# -# In some environments, certain algorithms or key lengths may be undesirable -# when using SSL/TLS. This section describes the mechanism for disabling -# algorithms during SSL/TLS security parameters negotiation, including cipher -# suites selection, peer authentication and key exchange mechanisms. -# -# For PKI-based peer authentication and key exchange mechanisms, this list -# of disabled algorithms will also be checked during certification path -# building and validation, including algorithms used in certificates, as -# well as revocation information such as CRLs and signed OCSP Responses. -# This is in addition to the jdk.certpath.disabledAlgorithms property above. -# -# See the specification of "jdk.certpath.disabledAlgorithms" for the -# syntax of the disabled algorithm string. -# -# Note: This property is currently used by Oracle's JSSE implementation. -# It is not guaranteed to be examined and used by other implementations. -# -# Example: -# jdk.tls.disabledAlgorithms=MD5, SHA1, DSA, RSA keySize < 2048 diff --git a/jdk/src/java.base/share/native/libjava/FileInputStream.c b/jdk/src/java.base/share/native/libjava/FileInputStream.c index 092ddbf6f1f..dc1aea5cd64 100644 --- a/jdk/src/java.base/share/native/libjava/FileInputStream.c +++ b/jdk/src/java.base/share/native/libjava/FileInputStream.c @@ -57,7 +57,7 @@ Java_java_io_FileInputStream_initIDs(JNIEnv *env, jclass fdClass) { */ JNIEXPORT void JNICALL -Java_java_io_FileInputStream_open(JNIEnv *env, jobject this, jstring path) { +Java_java_io_FileInputStream_open0(JNIEnv *env, jobject this, jstring path) { fileOpen(env, this, path, fis_fd, O_RDONLY); } diff --git a/jdk/src/java.base/share/native/libjava/RandomAccessFile.c b/jdk/src/java.base/share/native/libjava/RandomAccessFile.c index 53b5f1aac1f..a44d8f39681 100644 --- a/jdk/src/java.base/share/native/libjava/RandomAccessFile.c +++ b/jdk/src/java.base/share/native/libjava/RandomAccessFile.c @@ -47,8 +47,8 @@ Java_java_io_RandomAccessFile_initIDs(JNIEnv *env, jclass fdClass) { JNIEXPORT void JNICALL -Java_java_io_RandomAccessFile_open(JNIEnv *env, - jobject this, jstring path, jint mode) +Java_java_io_RandomAccessFile_open0(JNIEnv *env, + jobject this, jstring path, jint mode) { int flags = 0; if (mode & java_io_RandomAccessFile_O_RDONLY) diff --git a/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java b/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java index e696d3eba07..2bb712e7867 100644 --- a/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java +++ b/jdk/src/java.base/unix/classes/sun/nio/ch/InheritedChannel.java @@ -226,6 +226,7 @@ class InheritedChannel { // -- Native methods -- + private static native void initIDs(); private static native int dup(int fd) throws IOException; private static native void dup2(int fd, int fd2) throws IOException; private static native int open0(String path, int oflag) throws IOException; @@ -236,5 +237,6 @@ class InheritedChannel { static { IOUtil.load(); + initIDs(); } } diff --git a/jdk/src/java.base/unix/native/libjava/FileOutputStream_md.c b/jdk/src/java.base/unix/native/libjava/FileOutputStream_md.c index efd5864cd9c..22d80a22663 100644 --- a/jdk/src/java.base/unix/native/libjava/FileOutputStream_md.c +++ b/jdk/src/java.base/unix/native/libjava/FileOutputStream_md.c @@ -53,8 +53,8 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fdClass) { */ JNIEXPORT void JNICALL -Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, - jstring path, jboolean append) { +Java_java_io_FileOutputStream_open0(JNIEnv *env, jobject this, + jstring path, jboolean append) { fileOpen(env, this, path, fos_fd, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC)); } diff --git a/jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c b/jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c index da5be2257d0..18dee4ddd41 100644 --- a/jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c +++ b/jdk/src/java.base/unix/native/libjava/UNIXProcess_md.c @@ -599,9 +599,9 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, */ assert(prog != NULL && argBlock != NULL); if ((phelperpath = getBytes(env, helperpath)) == NULL) goto Catch; - if ((pprog = getBytes(env, prog)) == NULL) goto Catch; - if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch; - if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch; + if ((pprog = getBytes(env, prog)) == NULL) goto Catch; + if ((pargBlock = getBytes(env, argBlock)) == NULL) goto Catch; + if ((c->argv = NEW(const char *, argc + 3)) == NULL) goto Catch; c->argv[0] = pprog; c->argc = argc + 2; initVectorFromBlock(c->argv+1, pargBlock, argc); @@ -690,10 +690,11 @@ Java_java_lang_UNIXProcess_forkAndExec(JNIEnv *env, closeSafely(childenv[0]); closeSafely(childenv[1]); - releaseBytes(env, prog, pprog); - releaseBytes(env, argBlock, pargBlock); - releaseBytes(env, envBlock, penvBlock); - releaseBytes(env, dir, c->pdir); + releaseBytes(env, helperpath, phelperpath); + releaseBytes(env, prog, pprog); + releaseBytes(env, argBlock, pargBlock); + releaseBytes(env, envBlock, penvBlock); + releaseBytes(env, dir, c->pdir); free(c->argv); free(c->envv); diff --git a/jdk/src/java.base/unix/native/libnio/ch/IOUtil.c b/jdk/src/java.base/unix/native/libnio/ch/IOUtil.c index d8bbe849252..438bf41ddea 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/IOUtil.c +++ b/jdk/src/java.base/unix/native/libnio/ch/IOUtil.c @@ -35,7 +35,6 @@ #include "java_lang_Integer.h" #include "nio.h" #include "nio_util.h" -#include "net_util.h" static jfieldID fd_fdID; /* for jint 'fd' in java.io.FileDescriptor */ @@ -45,7 +44,6 @@ Java_sun_nio_ch_IOUtil_initIDs(JNIEnv *env, jclass clazz) { CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor")); CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I")); - initInetAddressIDs(env); } JNIEXPORT jboolean JNICALL diff --git a/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c b/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c index 986348e5320..86d1b05baa2 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c +++ b/jdk/src/java.base/unix/native/libnio/ch/InheritedChannel.c @@ -47,6 +47,13 @@ static int matchFamily(struct sockaddr *sa) { return (family == AF_INET); } +JNIEXPORT void JNICALL +Java_sun_nio_ch_InheritedChannel_initIDs(JNIEnv *env, jclass cla) +{ + /* Initialize InetAddress IDs before later use of NET_XXX functions */ + initInetAddressIDs(env); +} + JNIEXPORT jobject JNICALL Java_sun_nio_ch_InheritedChannel_peerAddress0(JNIEnv *env, jclass cla, jint fd) { diff --git a/jdk/src/java.base/unix/native/libnio/ch/Net.c b/jdk/src/java.base/unix/native/libnio/ch/Net.c index 8887f59109c..197b23a7285 100644 --- a/jdk/src/java.base/unix/native/libnio/ch/Net.c +++ b/jdk/src/java.base/unix/native/libnio/ch/Net.c @@ -151,7 +151,7 @@ static jboolean isSourceFilterSupported(){ JNIEXPORT void JNICALL Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) { - /* Here because Windows native code does need to init IDs */ + initInetAddressIDs(env); } JNIEXPORT jboolean JNICALL diff --git a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c index d3ee3279e54..e8a1623a87d 100644 --- a/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c +++ b/jdk/src/java.base/unix/native/libnio/fs/UnixNativeDispatcher.c @@ -333,7 +333,7 @@ Java_sun_nio_fs_UnixNativeDispatcher_dup(JNIEnv* env, jclass this, jint fd) { int res = -1; RESTARTABLE(dup((int)fd), res); - if (fd == -1) { + if (res == -1) { throwUnixException(env, errno); } return (jint)res; @@ -361,13 +361,14 @@ Java_sun_nio_fs_UnixNativeDispatcher_fopen0(JNIEnv* env, jclass this, JNIEXPORT void JNICALL Java_sun_nio_fs_UnixNativeDispatcher_fclose(JNIEnv* env, jclass this, jlong stream) { - int res; FILE* fp = jlong_to_ptr(stream); - do { - res = fclose(fp); - } while (res == EOF && errno == EINTR); - if (res == EOF) { + /* NOTE: fclose() wrapper is only used with read-only streams. + * If it ever is used with write streams, it might be better to add + * RESTARTABLE(fflush(fp)) before closing, to make sure the stream + * is completely written even if fclose() failed. + */ + if (fclose(fp) == EOF && errno != EINTR) { throwUnixException(env, errno); } } @@ -675,11 +676,9 @@ Java_sun_nio_fs_UnixNativeDispatcher_fdopendir(JNIEnv* env, jclass this, int dfd JNIEXPORT void JNICALL Java_sun_nio_fs_UnixNativeDispatcher_closedir(JNIEnv* env, jclass this, jlong dir) { - int err; DIR* dirp = jlong_to_ptr(dir); - RESTARTABLE(closedir(dirp), err); - if (errno == -1) { + if (closedir(dirp) == -1 && errno != EINTR) { throwUnixException(env, errno); } } diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java index d20d12fb053..82a4bc3aecd 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsNativeDispatcher.java @@ -36,6 +36,17 @@ import sun.misc.Unsafe; class WindowsNativeDispatcher { private WindowsNativeDispatcher() { } + /** + * HANDLE CreateEvent( + * LPSECURITY_ATTRIBUTES lpEventAttributes, + * BOOL bManualReset, + * BOOL bInitialState, + * PCTSTR lpName + * ); + */ + static native long CreateEvent(boolean bManualReset, boolean bInitialState) + throws WindowsException; + /** * HANDLE CreateFile( * LPCTSTR lpFileName, @@ -1041,6 +1052,25 @@ class WindowsNativeDispatcher { long pOverlapped) throws WindowsException; + + /** + * CancelIo( + * HANDLE hFile + * ) + */ + static native void CancelIo(long hFile) throws WindowsException; + + /** + * GetOverlappedResult( + * HANDLE hFile, + * LPOVERLAPPED lpOverlapped, + * LPDWORD lpNumberOfBytesTransferred, + * BOOL bWait + * ); + */ + static native int GetOverlappedResult(long hFile, long lpOverlapped) + throws WindowsException; + /** * BackupRead( * HANDLE hFile, diff --git a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java index 6677c874348..737c485698f 100644 --- a/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java +++ b/jdk/src/java.base/windows/classes/sun/nio/fs/WindowsWatchService.java @@ -25,9 +25,16 @@ package sun.nio.fs; -import java.nio.file.*; import java.io.IOException; -import java.util.*; +import java.nio.file.NotDirectoryException; +import java.nio.file.Path; +import java.nio.file.StandardWatchEventKinds; +import java.nio.file.WatchEvent; +import java.nio.file.WatchKey; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + import com.sun.nio.file.ExtendedWatchEventModifier; import sun.misc.Unsafe; @@ -42,7 +49,6 @@ class WindowsWatchService extends AbstractWatchService { private final static int WAKEUP_COMPLETION_KEY = 0; - private final Unsafe unsafe = Unsafe.getUnsafe(); // background thread to service I/O completion port private final Poller poller; @@ -82,7 +88,7 @@ class WindowsWatchService /** * Windows implementation of WatchKey. */ - private class WindowsWatchKey extends AbstractWatchKey { + private static class WindowsWatchKey extends AbstractWatchKey { // file key (used to detect existing registrations) private final FileKey fileKey; @@ -169,15 +175,9 @@ class WindowsWatchService return completionKey; } - // close directory and release buffer - void releaseResources() { - CloseHandle(handle); - buffer.cleaner().clean(); - } - - // Invalidate key by closing directory and releasing buffer + // Invalidate the key, assumes that resources have been released void invalidate() { - releaseResources(); + ((WindowsWatchService)watcher()).poller.releaseResources(this); handle = INVALID_HANDLE_VALUE; buffer = null; countAddress = 0; @@ -193,7 +193,7 @@ class WindowsWatchService public void cancel() { if (isValid()) { // delegate to poller - poller.cancel(this); + ((WindowsWatchService)watcher()).poller.cancel(this); } } } @@ -241,18 +241,25 @@ class WindowsWatchService /** * Background thread to service I/O completion port. */ - private class Poller extends AbstractPoller { + private static class Poller extends AbstractPoller { + private final static Unsafe UNSAFE = Unsafe.getUnsafe(); + /* * typedef struct _OVERLAPPED { - * DWORD Internal; - * DWORD InternalHigh; - * DWORD Offset; - * DWORD OffsetHigh; - * HANDLE hEvent; + * ULONG_PTR Internal; + * ULONG_PTR InternalHigh; + * union { + * struct { DWORD Offset; DWORD OffsetHigh; }; + * PVOID Pointer; + * }; + * HANDLE hEvent; * } OVERLAPPED; */ private static final short SIZEOF_DWORD = 4; private static final short SIZEOF_OVERLAPPED = 32; // 20 on 32-bit + private static final short OFFSETOF_HEVENT = + (UNSAFE.addressSize() == 4) ? (short) 16 : 24; + /* * typedef struct _FILE_NOTIFY_INFORMATION { @@ -276,10 +283,10 @@ class WindowsWatchService private final long port; // maps completion key to WatchKey - private final Map ck2key; + private final Map ck2key; // maps file key to WatchKey - private final Map fk2key; + private final Map fk2key; // unique completion key for each directory // native completion key capacity is 64 bits on Win64. @@ -393,8 +400,13 @@ class WindowsWatchService long overlappedAddress = bufferAddress + size - SIZEOF_OVERLAPPED; long countAddress = overlappedAddress - SIZEOF_DWORD; + // zero the overlapped structure + UNSAFE.setMemory(overlappedAddress, SIZEOF_OVERLAPPED, (byte)0); + // start async read of changes to directory try { + createAndAttachEvent(overlappedAddress); + ReadDirectoryChangesW(handle, bufferAddress, CHANGES_BUFFER_SIZE, @@ -403,6 +415,7 @@ class WindowsWatchService countAddress, overlappedAddress); } catch (WindowsException x) { + closeAttachedEvent(overlappedAddress); buffer.release(); return new IOException(x.getMessage()); } @@ -421,7 +434,7 @@ class WindowsWatchService // 2. release existing key's resources (handle/buffer) // 3. re-initialize key with new handle/buffer ck2key.remove(existing.completionKey()); - existing.releaseResources(); + releaseResources(existing); watchKey = existing.init(handle, events, watchSubtree, buffer, countAddress, overlappedAddress, completionKey); } @@ -436,6 +449,42 @@ class WindowsWatchService } } + /** + * Cancels the outstanding I/O operation on the directory + * associated with the given key and releases the associated + * resources. + */ + private void releaseResources(WindowsWatchKey key) { + try { + CancelIo(key.handle()); + GetOverlappedResult(key.handle(), key.overlappedAddress()); + } catch (WindowsException expected) { + // expected as I/O operation has been cancelled + } + CloseHandle(key.handle()); + closeAttachedEvent(key.overlappedAddress()); + key.buffer().cleaner().clean(); + } + + /** + * Creates an unnamed event and set it as the hEvent field + * in the given OVERLAPPED structure + */ + private void createAndAttachEvent(long ov) throws WindowsException { + long hEvent = CreateEvent(false, false); + UNSAFE.putAddress(ov + OFFSETOF_HEVENT, hEvent); + } + + /** + * Closes the event attached to the given OVERLAPPED structure. A + * no-op if there isn't an event attached. + */ + private void closeAttachedEvent(long ov) { + long hEvent = UNSAFE.getAddress(ov + OFFSETOF_HEVENT); + if (hEvent != 0 && hEvent != INVALID_HANDLE_VALUE) + CloseHandle(hEvent); + } + // cancel single key @Override void implCancelKey(WatchKey obj) { @@ -451,9 +500,8 @@ class WindowsWatchService @Override void implCloseAll() { // cancel all keys - for (Map.Entry entry: ck2key.entrySet()) { - entry.getValue().invalidate(); - } + ck2key.values().forEach(WindowsWatchKey::invalidate); + fk2key.clear(); ck2key.clear(); @@ -462,8 +510,7 @@ class WindowsWatchService } // Translate file change action into watch event - private WatchEvent.Kind translateActionToEvent(int action) - { + private WatchEvent.Kind translateActionToEvent(int action) { switch (action) { case FILE_ACTION_MODIFIED : return StandardWatchEventKinds.ENTRY_MODIFY; @@ -487,18 +534,18 @@ class WindowsWatchService int nextOffset; do { - int action = unsafe.getInt(address + OFFSETOF_ACTION); + int action = UNSAFE.getInt(address + OFFSETOF_ACTION); // map action to event WatchEvent.Kind kind = translateActionToEvent(action); if (key.events().contains(kind)) { // copy the name - int nameLengthInBytes = unsafe.getInt(address + OFFSETOF_FILENAMELENGTH); + int nameLengthInBytes = UNSAFE.getInt(address + OFFSETOF_FILENAMELENGTH); if ((nameLengthInBytes % 2) != 0) { - throw new AssertionError("FileNameLength.FileNameLength is not a multiple of 2"); + throw new AssertionError("FileNameLength is not a multiple of 2"); } char[] nameAsArray = new char[nameLengthInBytes/2]; - unsafe.copyMemory(null, address + OFFSETOF_FILENAME, nameAsArray, + UNSAFE.copyMemory(null, address + OFFSETOF_FILENAME, nameAsArray, Unsafe.ARRAY_CHAR_BASE_OFFSET, nameLengthInBytes); // create FileName and queue event @@ -508,7 +555,7 @@ class WindowsWatchService } // next event - nextOffset = unsafe.getInt(address + OFFSETOF_NEXTENTRYOFFSET); + nextOffset = UNSAFE.getInt(address + OFFSETOF_NEXTENTRYOFFSET); address += (long)nextOffset; } while (nextOffset != 0); } diff --git a/jdk/src/java.base/windows/native/libjava/FileOutputStream_md.c b/jdk/src/java.base/windows/native/libjava/FileOutputStream_md.c index 567ebaa0c83..02ea15e89cb 100644 --- a/jdk/src/java.base/windows/native/libjava/FileOutputStream_md.c +++ b/jdk/src/java.base/windows/native/libjava/FileOutputStream_md.c @@ -54,8 +54,8 @@ Java_java_io_FileOutputStream_initIDs(JNIEnv *env, jclass fosClass) { */ JNIEXPORT void JNICALL -Java_java_io_FileOutputStream_open(JNIEnv *env, jobject this, - jstring path, jboolean append) { +Java_java_io_FileOutputStream_open0(JNIEnv *env, jobject this, + jstring path, jboolean append) { fileOpen(env, this, path, fos_fd, O_WRONLY | O_CREAT | (append ? O_APPEND : O_TRUNC)); } diff --git a/jdk/src/java.base/windows/native/libjava/WinNTFileSystem_md.c b/jdk/src/java.base/windows/native/libjava/WinNTFileSystem_md.c index 6ecf818d3ff..3c280c0c9b4 100644 --- a/jdk/src/java.base/windows/native/libjava/WinNTFileSystem_md.c +++ b/jdk/src/java.base/windows/native/libjava/WinNTFileSystem_md.c @@ -572,10 +572,10 @@ Java_java_io_WinNTFileSystem_createFileExclusively(JNIEnv *env, jclass cls, SetLastError(error); JNU_ThrowIOExceptionWithLastError(env, "Could not open file"); } - } - free(pathbuf); - return JNI_FALSE; } + free(pathbuf); + return JNI_FALSE; + } free(pathbuf); CloseHandle(h); return JNI_TRUE; @@ -636,7 +636,7 @@ Java_java_io_WinNTFileSystem_list(JNIEnv *env, jobject this, jobject file) if (search_path == 0) { free (pathbuf); errno = ENOMEM; - JNU_ThrowOutOfMemoryError(env, "native memory allocation faiuled"); + JNU_ThrowOutOfMemoryError(env, "native memory allocation failed"); return NULL; } wcscpy(search_path, pathbuf); @@ -652,7 +652,7 @@ Java_java_io_WinNTFileSystem_list(JNIEnv *env, jobject this, jobject file) /* Remove trailing space chars from directory name */ len = (int)wcslen(search_path); - while (search_path[len-1] == ' ') { + while (search_path[len-1] == L' ') { len--; } search_path[len] = 0; @@ -713,13 +713,15 @@ Java_java_io_WinNTFileSystem_list(JNIEnv *env, jobject this, jobject file) return NULL; // error FindClose(handle); - /* Copy the final results into an appropriately-sized array */ - old = rv; - rv = (*env)->NewObjectArray(env, len, str_class, NULL); - if (rv == NULL) - return NULL; /* error */ - if (JNU_CopyObjectArray(env, rv, old, len) < 0) - return NULL; /* error */ + if (len < maxlen) { + /* Copy the final results into an appropriately-sized array */ + old = rv; + rv = (*env)->NewObjectArray(env, len, str_class, NULL); + if (rv == NULL) + return NULL; /* error */ + if (JNU_CopyObjectArray(env, rv, old, len) < 0) + return NULL; /* error */ + } return rv; } @@ -753,9 +755,7 @@ Java_java_io_WinNTFileSystem_rename0(JNIEnv *env, jobject this, jobject from, jboolean rv = JNI_FALSE; WCHAR *frompath = fileToNTPath(env, from, ids.path); WCHAR *topath = fileToNTPath(env, to, ids.path); - if (frompath == NULL || topath == NULL) - return JNI_FALSE; - if (_wrename(frompath, topath) == 0) { + if (frompath != NULL && topath != NULL && _wrename(frompath, topath) == 0) { rv = JNI_TRUE; } free(frompath); diff --git a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c index 50c7630ebf8..abc9418a245 100644 --- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c +++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainDatagramSocketImpl.c @@ -493,6 +493,9 @@ Java_java_net_TwoStacksPlainDatagramSocketImpl_bind0(JNIEnv *env, jobject this, } } } else { + /* NET_BindV6() closes both sockets upon a failure */ + (*env)->SetObjectField(env, this, pdsi_fdID, NULL); + (*env)->SetObjectField(env, this, pdsi_fd1ID, NULL); NET_ThrowCurrent (env, "Cannot bind"); return; } diff --git a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c index ff86b249c44..facab5923f9 100644 --- a/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c +++ b/jdk/src/java.base/windows/native/libnet/TwoStacksPlainSocketImpl.c @@ -467,6 +467,10 @@ Java_java_net_TwoStacksPlainSocketImpl_socketBind(JNIEnv *env, jobject this, (*env)->SetIntField(env, fd1Obj, IO_fd_fdID, fd1); } } + } else { + /* NET_BindV6() closes both sockets upon a failure */ + (*env)->SetObjectField(env, this, psi_fdID, NULL); + (*env)->SetObjectField(env, this, psi_fd1ID, NULL); } } else { rv = NET_WinBind(fd, (struct sockaddr *)&him, len, exclBind); diff --git a/jdk/src/java.base/windows/native/libnet/net_util_md.c b/jdk/src/java.base/windows/native/libnet/net_util_md.c index 5f00f49dfd5..523973ba50f 100644 --- a/jdk/src/java.base/windows/native/libnet/net_util_md.c +++ b/jdk/src/java.base/windows/native/libnet/net_util_md.c @@ -627,7 +627,7 @@ void dumpAddr (char *str, void *addr) { * and returns SOCKET_ERROR. Used in NET_BindV6 only. */ -#define CLOSE_SOCKETS_AND_RETURN { \ +#define CLOSE_SOCKETS_AND_RETURN do { \ if (fd != -1) { \ closesocket (fd); \ fd = -1; \ @@ -646,7 +646,7 @@ void dumpAddr (char *str, void *addr) { } \ b->ipv4_fd = b->ipv6_fd = -1; \ return SOCKET_ERROR; \ -} +} while(0) /* * if ipv6 is available, call NET_BindV6 to bind to the required address/port. diff --git a/jdk/src/java.base/windows/native/libnio/ch/IOUtil.c b/jdk/src/java.base/windows/native/libnio/ch/IOUtil.c index 49de1eb89d7..5c33ac4de23 100644 --- a/jdk/src/java.base/windows/native/libnio/ch/IOUtil.c +++ b/jdk/src/java.base/windows/native/libnio/ch/IOUtil.c @@ -56,7 +56,6 @@ Java_sun_nio_ch_IOUtil_initIDs(JNIEnv *env, jclass clazz) CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor")); CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I")); CHECK_NULL(handle_fdID = (*env)->GetFieldID(env, clazz, "handle", "J")); - initInetAddressIDs(env); } /************************************************************** diff --git a/jdk/src/java.base/windows/native/libnio/ch/Net.c b/jdk/src/java.base/windows/native/libnio/ch/Net.c index fb0faa87b84..b92e63ac11b 100644 --- a/jdk/src/java.base/windows/native/libnio/ch/Net.c +++ b/jdk/src/java.base/windows/native/libnio/ch/Net.c @@ -81,7 +81,7 @@ static void setConnectionReset(SOCKET s, BOOL enable) { JNIEXPORT void JNICALL Java_sun_nio_ch_Net_initIDs(JNIEnv *env, jclass clazz) { - /* nothing to do */ + initInetAddressIDs(env); } JNIEXPORT jboolean JNICALL diff --git a/jdk/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c b/jdk/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c index 94e060fa193..8075d046763 100644 --- a/jdk/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c +++ b/jdk/src/java.base/windows/native/libnio/fs/WindowsNativeDispatcher.c @@ -195,6 +195,17 @@ Java_sun_nio_fs_WindowsNativeDispatcher_initIDs(JNIEnv* env, jclass this) } } +JNIEXPORT jlong JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_CreateEvent(JNIEnv* env, jclass this, + jboolean bManualReset, jboolean bInitialState) +{ + HANDLE hEvent = CreateEventW(NULL, bManualReset, bInitialState, NULL); + if (hEvent == NULL) { + throwWindowsException(env, GetLastError()); + } + return ptr_to_jlong(hEvent); +} + JNIEXPORT jstring JNICALL Java_sun_nio_fs_WindowsNativeDispatcher_FormatMessage(JNIEnv* env, jclass this, jint errorCode) { WCHAR message[255]; @@ -1229,6 +1240,31 @@ Java_sun_nio_fs_WindowsNativeDispatcher_PostQueuedCompletionStatus(JNIEnv* env, } } +JNIEXPORT void JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_CancelIo(JNIEnv* env, jclass this, jlong hFile) { + if (CancelIo((HANDLE)jlong_to_ptr(hFile)) == 0) { + throwWindowsException(env, GetLastError()); + } +} + +JNIEXPORT jint JNICALL +Java_sun_nio_fs_WindowsNativeDispatcher_GetOverlappedResult(JNIEnv *env, jclass this, + jlong hFile, jlong lpOverlapped) +{ + BOOL res; + DWORD bytesTransferred = -1; + + res = GetOverlappedResult((HANDLE)jlong_to_ptr(hFile), + (LPOVERLAPPED)jlong_to_ptr(lpOverlapped), + &bytesTransferred, + TRUE); + if (res == 0) { + throwWindowsException(env, GetLastError()); + } + + return (jint)bytesTransferred; +} + JNIEXPORT void JNICALL Java_sun_nio_fs_WindowsNativeDispatcher_ReadDirectoryChangesW(JNIEnv* env, jclass this, jlong hDirectory, jlong bufferAddress, jint bufferLength, jboolean watchSubTree, jint filter, @@ -1236,17 +1272,7 @@ Java_sun_nio_fs_WindowsNativeDispatcher_ReadDirectoryChangesW(JNIEnv* env, jclas { BOOL res; BOOL subtree = (watchSubTree == JNI_TRUE) ? TRUE : FALSE; - - /* Any unused members of [OVERLAPPED] structure should always be initialized to zero - before the structure is used in a function call. - Otherwise, the function may fail and return ERROR_INVALID_PARAMETER. - http://msdn.microsoft.com/en-us/library/windows/desktop/ms684342%28v=vs.85%29.aspx - - The [Offset] and [OffsetHigh] members of this structure are not used. - http://msdn.microsoft.com/en-us/library/windows/desktop/aa365465%28v=vs.85%29.aspx - - [hEvent] should be zero, other fields are the return values. */ - ZeroMemory((LPOVERLAPPED)jlong_to_ptr(pOverlapped), sizeof(OVERLAPPED)); + LPOVERLAPPED ov = (LPOVERLAPPED)jlong_to_ptr(pOverlapped); res = ReadDirectoryChangesW((HANDLE)jlong_to_ptr(hDirectory), (LPVOID)jlong_to_ptr(bufferAddress), diff --git a/jdk/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java b/jdk/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java index 28df9def412..eeed61d3798 100644 --- a/jdk/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java +++ b/jdk/src/java.desktop/macosx/classes/apple/laf/JRSUIControl.java @@ -114,7 +114,7 @@ public final class JRSUIControl { changes.putAll(other.changes); } - protected synchronized final void finalize() throws Throwable { + protected synchronized void finalize() throws Throwable { if (cfDictionaryPtr == 0) return; disposeCFDictionary(cfDictionaryPtr); cfDictionaryPtr = 0; diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameUI.java index 90ce8ca5b80..2ba95f6af05 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaInternalFrameUI.java @@ -938,7 +938,11 @@ public class AquaInternalFrameUI extends BasicInternalFrameUI implements SwingCo final Point pt = new Point(); final Component c = getComponentToForwardTo(e, pt); if (c == null) return; - c.dispatchEvent(new MouseWheelEvent(c, e.getID(), e.getWhen(), e.getModifiers(), pt.x, pt.y, e.getClickCount(), e.isPopupTrigger(), e.getScrollType(), e.getScrollAmount(), e.getWheelRotation())); + c.dispatchEvent(new MouseWheelEvent(c, e.getID(), e.getWhen(), + e.getModifiers(), pt.x, pt.y, e.getXOnScreen(), e.getYOnScreen(), + e.getClickCount(), e.isPopupTrigger(), e.getScrollType(), + e.getScrollAmount(), e.getWheelRotation(), + e.getPreciseWheelRotation())); } public void componentResized(final ComponentEvent e) { diff --git a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java index 8dd4fa60d2d..3e40b843449 100644 --- a/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java +++ b/jdk/src/java.desktop/macosx/classes/com/apple/laf/AquaTabbedPaneCopyFromBasicUI.java @@ -3307,7 +3307,7 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing pane.repaint(); } else if (name == "indexForTitle") { calculatedBaseline = false; - updateHtmlViews((Integer) e.getNewValue()); + updateHtmlViews((Integer) e.getNewValue(), false); } else if (name == "tabLayoutPolicy") { AquaTabbedPaneCopyFromBasicUI.this.uninstallUI(pane); AquaTabbedPaneCopyFromBasicUI.this.installUI(pane); @@ -3345,7 +3345,7 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing calculatedBaseline = false; } else if (name == "indexForNullComponent") { isRunsDirty = true; - updateHtmlViews((Integer) e.getNewValue()); + updateHtmlViews((Integer) e.getNewValue(), true); } else if (name == "font") { calculatedBaseline = false; } @@ -3464,10 +3464,10 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing return; } isRunsDirty = true; - updateHtmlViews(tp.indexOfComponent(child)); + updateHtmlViews(tp.indexOfComponent(child), true); } - private void updateHtmlViews(int index) { + private void updateHtmlViews(int index, boolean inserted) { final String title = tabPane.getTitleAt(index); final boolean isHTML = BasicHTML.isHTMLString(title); if (isHTML) { @@ -3475,16 +3475,24 @@ public class AquaTabbedPaneCopyFromBasicUI extends TabbedPaneUI implements Swing htmlViews = createHTMLVector(); } else { // Vector already exists final View v = BasicHTML.createHTMLView(tabPane, title); - htmlViews.insertElementAt(v, index); + setHtmlView(v, inserted, index); } } else { // Not HTML if (htmlViews != null) { // Add placeholder - htmlViews.insertElementAt(null, index); + setHtmlView(null, inserted, index); } // else nada! } updateMnemonics(); } + private void setHtmlView(View v, boolean inserted, int index) { + if (inserted || index >= htmlViews.size()) { + htmlViews.insertElementAt(v, index); + } else { + htmlViews.setElementAt(v, index); + } + } + public void componentRemoved(final ContainerEvent e) { final JTabbedPane tp = (JTabbedPane)e.getContainer(); final Component child = e.getChild(); diff --git a/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java b/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java index 8e1cead53c2..28c59712fe7 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java +++ b/jdk/src/java.desktop/macosx/classes/sun/font/CFontManager.java @@ -43,7 +43,7 @@ import sun.awt.HeadlessToolkit; import sun.awt.util.ThreadGroupUtils; import sun.lwawt.macosx.*; -public class CFontManager extends SunFontManager { +public final class CFontManager extends SunFontManager { private FontConfigManager fcManager = null; private static Hashtable genericFonts = new Hashtable(); @@ -61,20 +61,14 @@ public class CFontManager extends SunFontManager { return new CFontConfiguration(this, preferLocaleFonts, preferPropFonts); } - private static String[] defaultPlatformFont = null; - /* * Returns an array of two strings. The first element is the * name of the font. The second element is the file name. */ @Override - public synchronized String[] getDefaultPlatformFont() { - if (defaultPlatformFont == null) { - defaultPlatformFont = new String[2]; - defaultPlatformFont[0] = "Lucida Grande"; - defaultPlatformFont[1] = "/System/Library/Fonts/LucidaGrande.ttc"; - } - return defaultPlatformFont; + protected String[] getDefaultPlatformFont() { + return new String[]{"Lucida Grande", + "/System/Library/Fonts/LucidaGrande.ttc"}; } // This is a way to register any kind of Font2D, not just files and composites. diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java index 408862f7746..ca731ba3a72 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWComponentPeer.java @@ -1233,11 +1233,13 @@ public abstract class LWComponentPeer delegate, me.getID(), me.getWhen(), me.getModifiers(), me.getX(), me.getY(), + me.getXOnScreen(), me.getYOnScreen(), me.getClickCount(), me.isPopupTrigger(), me.getScrollType(), me.getScrollAmount(), - me.getWheelRotation()); + me.getWheelRotation(), + me.getPreciseWheelRotation()); } else if (e instanceof MouseEvent) { MouseEvent me = (MouseEvent) e; diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java index 624be6bfc10..4491b7c9c05 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWLightweightFramePeer.java @@ -94,10 +94,12 @@ public class LWLightweightFramePeer extends LWWindowPeer { @Override public void addDropTarget(DropTarget dt) { + getLwTarget().addDropTarget(dt); } @Override public void removeDropTarget(DropTarget dt) { + getLwTarget().removeDropTarget(dt); } @Override diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java index b72ef77d876..4655d2bcfca 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/LWWindowPeer.java @@ -105,6 +105,8 @@ public class LWWindowPeer private final SecurityWarningWindow warningWindow; + private volatile boolean targetFocusable; + /** * Current modal blocker or null. * @@ -240,13 +242,12 @@ public class LWWindowPeer if (!visible && warningWindow != null) { warningWindow.setVisible(false, false); } - + updateFocusableWindowState(); super.setVisibleImpl(visible); // TODO: update graphicsConfig, see 4868278 platformWindow.setVisible(visible); if (isSimpleWindow()) { KeyboardFocusManagerPeer kfmPeer = LWKeyboardFocusManagerPeer.getInstance(); - if (visible) { if (!getTarget().isAutoRequestFocus()) { return; @@ -397,6 +398,7 @@ public class LWWindowPeer @Override public void updateFocusableWindowState() { + targetFocusable = getTarget().isFocusableWindow(); platformWindow.updateFocusableWindowState(); } @@ -1220,13 +1222,13 @@ public class LWWindowPeer } private boolean isFocusableWindow() { - boolean focusable = getTarget().isFocusableWindow(); + boolean focusable = targetFocusable; if (isSimpleWindow()) { LWWindowPeer ownerPeer = getOwnerFrameDialog(this); if (ownerPeer == null) { return false; } - return focusable && ownerPeer.getTarget().isFocusableWindow(); + return focusable && ownerPeer.targetFocusable; } return focusable; } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java index c241aae3cc0..7618bbec2a4 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/CEmbeddedFrame.java @@ -38,7 +38,8 @@ public class CEmbeddedFrame extends EmbeddedFrame { private CPlatformResponder responder; private static final Object classLock = new Object(); - private static volatile CEmbeddedFrame focusedWindow; + private static volatile CEmbeddedFrame globalFocusedWindow; + private CEmbeddedFrame browserWindowFocusedApplet; private boolean parentWindowActive = true; public CEmbeddedFrame() { @@ -111,10 +112,10 @@ public class CEmbeddedFrame extends EmbeddedFrame { synchronized (classLock) { // In some cases an applet may not receive the focus lost event // from the parent window (see 8012330) - focusedWindow = (focused) ? this - : ((focusedWindow == this) ? null : focusedWindow); + globalFocusedWindow = (focused) ? this + : ((globalFocusedWindow == this) ? null : globalFocusedWindow); } - if (focusedWindow == this) { + if (globalFocusedWindow == this) { // see bug 8010925 // we can't put this to handleWindowFocusEvent because // it won't be invoced if focuse is moved to a html element @@ -145,9 +146,23 @@ public class CEmbeddedFrame extends EmbeddedFrame { // non-focused applet. This method can be called from different threads. public void handleWindowFocusEvent(boolean parentWindowActive) { this.parentWindowActive = parentWindowActive; + // If several applets are running in different browser's windows, it is necessary to + // detect the switching between the parent windows and update globalFocusedWindow accordingly. + synchronized (classLock) { + if (!parentWindowActive) { + this.browserWindowFocusedApplet = globalFocusedWindow; + } + if (parentWindowActive && globalFocusedWindow != this && isParentWindowChanged()) { + // It looks like we have switched to another browser window, let's restore focus to + // the previously focused applet in this window. If no applets were focused in the + // window, we will set focus to the first applet in the window. + globalFocusedWindow = (this.browserWindowFocusedApplet != null) ? this.browserWindowFocusedApplet + : this; + } + } // ignore focus "lost" native request as it may mistakenly // deactivate active window (see 8001161) - if (focusedWindow == this && parentWindowActive) { + if (globalFocusedWindow == this && parentWindowActive) { responder.handleWindowFocusEvent(parentWindowActive, null); } } @@ -155,4 +170,10 @@ public class CEmbeddedFrame extends EmbeddedFrame { public boolean isParentWindowActive() { return parentWindowActive; } + + private boolean isParentWindowChanged() { + // If globalFocusedWindow is located at inactive parent window or null, we have swithed to + // another window. + return globalFocusedWindow != null ? !globalFocusedWindow.isParentWindowActive() : true; + } } diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java index 768086220c3..b184ec0759f 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/LWCToolkit.java @@ -688,6 +688,11 @@ public final class LWCToolkit extends LWToolkit { @Override public DragSourceContextPeer createDragSourceContextPeer( DragGestureEvent dge) throws InvalidDnDOperationException { + final LightweightFrame f = SunToolkit.getLightweightFrame(dge.getComponent()); + if (f != null) { + return f.createDragSourceContextPeer(dge); + } + return CDragSourceContextPeer.createDragSourceContextPeer(dge); } @@ -696,6 +701,11 @@ public final class LWCToolkit extends LWToolkit { public T createDragGestureRecognizer( Class abstractRecognizerClass, DragSource ds, Component c, int srcActions, DragGestureListener dgl) { + final LightweightFrame f = SunToolkit.getLightweightFrame(c); + if (f != null) { + return f.createDragGestureRecognizer(abstractRecognizerClass, ds, c, srcActions, dgl); + } + DragGestureRecognizer dgr = null; // Create a new mouse drag gesture recognizer if we have a class match: diff --git a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSPrintInfo.java b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSPrintInfo.java index 16bada2688c..7a33fdf22e2 100644 --- a/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSPrintInfo.java +++ b/jdk/src/java.desktop/macosx/classes/sun/lwawt/macosx/NSPrintInfo.java @@ -54,11 +54,11 @@ public final class NSPrintInfo implements PrintJobAttribute, PrintRequestAttribu return "" + fNSPrintInfo; } - public final Class getCategory() { + public Class getCategory() { return NSPrintInfo.class; } - public final String getName() { + public String getName() { return "nsPrintInfo"; } } diff --git a/jdk/src/java.desktop/macosx/native/libawt_lwawt/sun/awt/JavaComponentAccessibility.m b/jdk/src/java.desktop/macosx/native/libawt_lwawt/sun/awt/JavaComponentAccessibility.m index e0de79524e8..1b3ec43a9fe 100644 --- a/jdk/src/java.desktop/macosx/native/libawt_lwawt/sun/awt/JavaComponentAccessibility.m +++ b/jdk/src/java.desktop/macosx/native/libawt_lwawt/sun/awt/JavaComponentAccessibility.m @@ -1108,7 +1108,10 @@ static NSObject *sAttributeNamesLOCK = nil; JNIEnv *env = [ThreadUtilities getJNIEnv]; id value = nil; + NSWindow* hostWindow = [[self->fView window] retain]; jobject focused = JNFCallStaticObjectMethod(env, jm_getFocusOwner, fComponent); // AWT_THREADING Safe (AWTRunLoop) + [hostWindow release]; + if (focused != NULL) { if (JNFIsInstanceOf(env, focused, &sjc_Accessible)) { value = [JavaComponentAccessibility createWithAccessible:focused withEnv:env withView:fView]; diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/FFT.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/FFT.java index b378c8cc65d..8b1436736c0 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/FFT.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/FFT.java @@ -68,7 +68,7 @@ public final class FFT { calc(fftFrameSize, data, sign, w); } - private final static double[] computeTwiddleFactors(int fftFrameSize, + private static double[] computeTwiddleFactors(int fftFrameSize, int sign) { int imax = (int) (Math.log(fftFrameSize) / Math.log(2.)); @@ -122,7 +122,7 @@ public final class FFT { return warray; } - private final static void calc(int fftFrameSize, double[] data, int sign, + private static void calc(int fftFrameSize, double[] data, int sign, double[] w) { final int fftFrameSize2 = fftFrameSize << 1; @@ -139,7 +139,7 @@ public final class FFT { } - private final static void calcF2E(int fftFrameSize, double[] data, int i, + private static void calcF2E(int fftFrameSize, double[] data, int i, int nstep, double[] w) { int jmax = nstep; for (int n = 0; n < jmax; n += 2) { @@ -163,7 +163,7 @@ public final class FFT { // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- // complex operators - private final static void calcF4F(int fftFrameSize, double[] data, int i, + private static void calcF4F(int fftFrameSize, double[] data, int i, int nstep, double[] w) { final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; // Factor-4 Decomposition @@ -331,7 +331,7 @@ public final class FFT { // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- // complex operators - private final static void calcF4I(int fftFrameSize, double[] data, int i, + private static void calcF4I(int fftFrameSize, double[] data, int i, int nstep, double[] w) { final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; // Factor-4 Decomposition @@ -499,7 +499,7 @@ public final class FFT { // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- // complex operators - private final static void calcF4FE(int fftFrameSize, double[] data, int i, + private static void calcF4FE(int fftFrameSize, double[] data, int i, int nstep, double[] w) { final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; // Factor-4 Decomposition @@ -593,7 +593,7 @@ public final class FFT { // Perform Factor-4 Decomposition with 3 * complex operators and 8 +/- // complex operators - private final static void calcF4IE(int fftFrameSize, double[] data, int i, + private static void calcF4IE(int fftFrameSize, double[] data, int i, int nstep, double[] w) { final int fftFrameSize2 = fftFrameSize << 1; // 2*fftFrameSize; // Factor-4 Decomposition @@ -685,7 +685,7 @@ public final class FFT { } - private final void bitreversal(double[] data) { + private void bitreversal(double[] data) { if (fftFrameSize < 4) return; diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JDK13Services.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JDK13Services.java index 9c93d06dc23..3805bb8848c 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JDK13Services.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JDK13Services.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,6 +25,8 @@ package com.sun.media.sound; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -176,11 +178,11 @@ public final class JDK13Services { && !Sequencer.class.equals(typeClass)) { return null; } - String value; - String propertyName = typeClass.getName(); - value = JSSecurityManager.getProperty(propertyName); + String name = typeClass.getName(); + String value = AccessController.doPrivileged( + (PrivilegedAction) () -> System.getProperty(name)); if (value == null) { - value = getProperties().getProperty(propertyName); + value = getProperties().getProperty(name); } if ("".equals(value)) { value = null; diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java index 60549a77ea4..6614b088cf3 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/JSSecurityManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -73,33 +73,6 @@ final class JSSecurityManager { } } - static String getProperty(final String propertyName) { - String propertyValue; - if (hasSecurityManager()) { - if(Printer.debug) Printer.debug("using JDK 1.2 security to get property"); - try{ - PrivilegedAction action = new PrivilegedAction() { - public String run() { - try { - return System.getProperty(propertyName); - } catch (Throwable t) { - return null; - } - } - }; - propertyValue = AccessController.doPrivileged(action); - } catch( Exception e ) { - if(Printer.debug) Printer.debug("not using JDK 1.2 security to get properties"); - propertyValue = System.getProperty(propertyName); - } - } else { - if(Printer.debug) Printer.debug("not using JDK 1.2 security to get properties"); - propertyValue = System.getProperty(propertyName); - } - return propertyValue; - } - - /** Load properties from a file. This method tries to load properties from the filename give into the passed properties object. diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/Platform.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/Platform.java index 766e485f120..493aa7e0bd5 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/Platform.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/Platform.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -74,17 +74,6 @@ final class Platform { // intel is little-endian. sparc is big-endian. private static boolean bigEndian; - // this is the value of the "java.home" system property. i am looking it up here - // for use when trying to load the soundbank, just so - // that all the privileged code is localized in this file.... - private static String javahome; - - // this is the value of the "java.class.path" system property - private static String classpath; - - - - static { if(Printer.trace)Printer.trace(">> Platform.java: static"); @@ -129,26 +118,6 @@ final class Platform { return signed8; } - - /** - * Obtain javahome. - * $$kk: 04.16.99: this is *bad*!! - */ - static String getJavahome() { - - return javahome; - } - - /** - * Obtain classpath. - * $$jb: 04.21.99: this is *bad* too!! - */ - static String getClasspath() { - - return classpath; - } - - // PRIVATE METHODS /** @@ -157,21 +126,13 @@ final class Platform { private static void loadLibraries() { if(Printer.trace)Printer.trace(">>Platform.loadLibraries"); - try { - // load the main library - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - System.loadLibrary(libNameMain); - return null; - } - }); - // just for the heck of it... - loadedLibs |= LIB_MAIN; - } catch (SecurityException e) { - if(Printer.err)Printer.err("Security exception loading main native library. JavaSound requires access to these resources."); - throw(e); - } + // load the main library + AccessController.doPrivileged((PrivilegedAction) () -> { + System.loadLibrary(libNameMain); + return null; + }); + // just for the heck of it... + loadedLibs |= LIB_MAIN; // now try to load extra libs. They are defined at compile time in the Makefile // with the define EXTRA_SOUND_JNI_LIBS @@ -181,12 +142,9 @@ final class Platform { while (st.hasMoreTokens()) { final String lib = st.nextToken(); try { - AccessController.doPrivileged(new PrivilegedAction() { - @Override - public Void run() { - System.loadLibrary(lib); - return null; - } + AccessController.doPrivileged((PrivilegedAction) () -> { + System.loadLibrary(lib); + return null; }); if (lib.equals(libNameALSA)) { @@ -239,7 +197,5 @@ final class Platform { // $$fb 2002-03-06: implement check for endianness in native. Facilitates porting ! bigEndian = nIsBigEndian(); signed8 = nIsSigned8(); // Solaris on Sparc: signed, all others unsigned - javahome = JSSecurityManager.getProperty("java.home"); - classpath = JSSecurityManager.getProperty("java.class.path"); } } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RIFFReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RIFFReader.java index 7969a5d4fce..9849fbcb961 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/RIFFReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/RIFFReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -39,21 +39,20 @@ public final class RIFFReader extends InputStream { private long filepointer = 0; private final String fourcc; private String riff_type = null; - private long ckSize = 0; + private long ckSize = Integer.MAX_VALUE; private InputStream stream; - private long avail; + private long avail = Integer.MAX_VALUE; private RIFFReader lastiterator = null; public RIFFReader(InputStream stream) throws IOException { - if (stream instanceof RIFFReader) - root = ((RIFFReader)stream).root; - else + if (stream instanceof RIFFReader) { + root = ((RIFFReader) stream).root; + } else { root = this; + } this.stream = stream; - avail = Integer.MAX_VALUE; - ckSize = Integer.MAX_VALUE; // Check for RIFF null paddings, int b; @@ -76,10 +75,12 @@ public final class RIFFReader extends InputStream { readFully(fourcc, 1, 3); this.fourcc = new String(fourcc, "ascii"); ckSize = readUnsignedInt(); - - avail = this.ckSize; + avail = ckSize; if (getFormat().equals("RIFF") || getFormat().equals("LIST")) { + if (avail > Integer.MAX_VALUE) { + throw new RIFFInvalidDataException("Chunk size too big"); + } byte[] format = new byte[4]; readFully(format); this.riff_type = new String(format, "ascii"); @@ -118,19 +119,23 @@ public final class RIFFReader extends InputStream { } public int read() throws IOException { - if (avail == 0) + if (avail == 0) { return -1; + } int b = stream.read(); - if (b == -1) + if (b == -1) { + avail = 0; return -1; + } avail--; filepointer++; return b; } public int read(byte[] b, int offset, int len) throws IOException { - if (avail == 0) + if (avail == 0) { return -1; + } if (len > avail) { int rlen = stream.read(b, offset, (int)avail); if (rlen != -1) @@ -139,19 +144,21 @@ public final class RIFFReader extends InputStream { return rlen; } else { int ret = stream.read(b, offset, len); - if (ret == -1) + if (ret == -1) { + avail = 0; return -1; + } avail -= ret; filepointer += ret; return ret; } } - public final void readFully(byte b[]) throws IOException { + public void readFully(byte b[]) throws IOException { readFully(b, 0, b.length); } - public final void readFully(byte b[], int off, int len) throws IOException { + public void readFully(byte b[], int off, int len) throws IOException { if (len < 0) throw new IndexOutOfBoundsException(); while (len > 0) { @@ -165,7 +172,7 @@ public final class RIFFReader extends InputStream { } } - public final long skipBytes(long n) throws IOException { + public long skipBytes(long n) throws IOException { if (n < 0) return 0; long skipped = 0; @@ -191,8 +198,10 @@ public final class RIFFReader extends InputStream { return len; } else { long ret = stream.skip(n); - if (ret == -1) + if (ret == -1) { + avail = 0; return -1; + } avail -= ret; filepointer += ret; return ret; @@ -210,8 +219,13 @@ public final class RIFFReader extends InputStream { } // Read ASCII chars from stream - public String readString(int len) throws IOException { - byte[] buff = new byte[len]; + public String readString(final int len) throws IOException { + final byte[] buff; + try { + buff = new byte[len]; + } catch (final OutOfMemoryError oom) { + throw new IOException("Length too big", oom); + } readFully(buff); for (int i = 0; i < buff.length; i++) { if (buff[i] == 0) { diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SF2Soundbank.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SF2Soundbank.java index 83c8848b4f9..d45d50162bb 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SF2Soundbank.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SF2Soundbank.java @@ -276,6 +276,9 @@ public final class SF2Soundbank implements Soundbank { count--; } + if (presets_bagNdx.isEmpty()) { + throw new RIFFInvalidDataException(); + } int offset = presets_bagNdx.get(0); // Offset should be 0 (but just case) for (int i = 0; i < offset; i++) { @@ -360,6 +363,9 @@ public final class SF2Soundbank implements Soundbank { count--; } + if (instruments_bagNdx.isEmpty()) { + throw new RIFFInvalidDataException(); + } int offset = instruments_bagNdx.get(0); // Offset should be 0 (but just case) for (int i = 0; i < offset; i++) { @@ -401,6 +407,9 @@ public final class SF2Soundbank implements Soundbank { modulator.amount = chunk.readShort(); modulator.amountSourceOperator = chunk.readUnsignedShort(); modulator.transportOperator = chunk.readUnsignedShort(); + if (i < 0 || i >= instruments_splits_gen.size()) { + throw new RIFFInvalidDataException(); + } SF2LayerRegion split = instruments_splits_gen.get(i); if (split != null) split.modulators.add(modulator); @@ -424,7 +433,8 @@ public final class SF2Soundbank implements Soundbank { sample.name = chunk.readString(20); long start = chunk.readUnsignedInt(); long end = chunk.readUnsignedInt(); - sample.data = sampleData.subbuffer(start * 2, end * 2, true); + if (sampleData != null) + sample.data = sampleData.subbuffer(start * 2, end * 2, true); if (sampleData24 != null) sample.data24 = sampleData24.subbuffer(start, end, true); /* @@ -462,6 +472,9 @@ public final class SF2Soundbank implements Soundbank { int sampleid = split.generators.get( SF2LayerRegion.GENERATOR_SAMPLEID); split.generators.remove(SF2LayerRegion.GENERATOR_SAMPLEID); + if (sampleid < 0 || sampleid >= samples.size()) { + throw new RIFFInvalidDataException(); + } split.sample = samples.get(sampleid); } else { globalsplit = split; @@ -488,6 +501,9 @@ public final class SF2Soundbank implements Soundbank { int instrumentid = split.generators.get( SF2InstrumentRegion.GENERATOR_INSTRUMENT); split.generators.remove(SF2LayerRegion.GENERATOR_INSTRUMENT); + if (instrumentid < 0 || instrumentid >= layers.size()) { + throw new RIFFInvalidDataException(); + } split.layer = layers.get(instrumentid); } else { globalsplit = split; diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java index 48ae72fcb02..5089a87199a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftMidiAudioFileReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 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 @@ -22,6 +22,7 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ + package com.sun.media.sound; import java.io.File; @@ -39,14 +40,14 @@ import javax.sound.midi.Receiver; import javax.sound.midi.Sequence; import javax.sound.midi.Track; import javax.sound.sampled.AudioFileFormat; +import javax.sound.sampled.AudioFileFormat.Type; import javax.sound.sampled.AudioFormat; import javax.sound.sampled.AudioInputStream; import javax.sound.sampled.UnsupportedAudioFileException; -import javax.sound.sampled.AudioFileFormat.Type; import javax.sound.sampled.spi.AudioFileReader; /** - * MIDI File Audio Renderer/Reader + * MIDI File Audio Renderer/Reader. * * @author Karl Helgason */ @@ -109,6 +110,9 @@ public final class SoftMidiAudioFileReader extends AudioFileReader { if (divtype == Sequence.PPQ) { if (((MetaMessage) msg).getType() == 0x51) { byte[] data = ((MetaMessage) msg).getData(); + if (data.length < 3) { + throw new UnsupportedAudioFileException(); + } mpq = ((data[0] & 0xff) << 16) | ((data[1] & 0xff) << 8) | (data[2] & 0xff); } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java index 2c6dff99fea..e895ead074f 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/SoftSynthesizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 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 @@ -28,6 +28,7 @@ package com.sun.media.sound; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; +import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; @@ -732,31 +733,28 @@ public final class SoftSynthesizer implements AudioSynthesizer, * Save generated soundbank to disk for faster future use. */ OutputStream out = AccessController - .doPrivileged(new PrivilegedAction() { - public OutputStream run() { - try { - File userhome = new File(System - .getProperty("user.home"), - ".gervill"); - if (!userhome.exists()) - userhome.mkdirs(); - File emg_soundbank_file = new File( - userhome, "soundbank-emg.sf2"); - if (emg_soundbank_file.exists()) - return null; - return new FileOutputStream( - emg_soundbank_file); - } catch (IOException e) { - } catch (SecurityException e) { + .doPrivileged((PrivilegedAction) () -> { + try { + File userhome = new File(System + .getProperty("user.home"), ".gervill"); + if (!userhome.exists()) { + userhome.mkdirs(); } - return null; + File emg_soundbank_file = new File( + userhome, "soundbank-emg.sf2"); + if (emg_soundbank_file.exists()) { + return null; + } + return new FileOutputStream(emg_soundbank_file); + } catch (final FileNotFoundException ignored) { } + return null; }); if (out != null) { try { ((SF2Soundbank) defaultSoundBank).save(out); out.close(); - } catch (IOException e) { + } catch (final IOException ignored) { } } } @@ -846,26 +844,24 @@ public final class SoftSynthesizer implements AudioSynthesizer, private Properties getStoredProperties() { return AccessController - .doPrivileged(new PrivilegedAction() { - public Properties run() { - Properties p = new Properties(); - String notePath = "/com/sun/media/sound/softsynthesizer"; - try { - Preferences prefroot = Preferences.userRoot(); - if (prefroot.nodeExists(notePath)) { - Preferences prefs = prefroot.node(notePath); - String[] prefs_keys = prefs.keys(); - for (String prefs_key : prefs_keys) { - String val = prefs.get(prefs_key, null); - if (val != null) - p.setProperty(prefs_key, val); + .doPrivileged((PrivilegedAction) () -> { + Properties p = new Properties(); + String notePath = "/com/sun/media/sound/softsynthesizer"; + try { + Preferences prefroot = Preferences.userRoot(); + if (prefroot.nodeExists(notePath)) { + Preferences prefs = prefroot.node(notePath); + String[] prefs_keys = prefs.keys(); + for (String prefs_key : prefs_keys) { + String val = prefs.get(prefs_key, null); + if (val != null) { + p.setProperty(prefs_key, val); } } - } catch (BackingStoreException e) { - } catch (SecurityException e) { } - return p; + } catch (final BackingStoreException ignored) { } + return p; }); } @@ -1044,7 +1040,6 @@ public final class SoftSynthesizer implements AudioSynthesizer, return; } synchronized (control_mutex) { - Throwable causeException = null; try { if (line != null) { // can throw IllegalArgumentException @@ -1117,24 +1112,17 @@ public final class SoftSynthesizer implements AudioSynthesizer, weakstream.sourceDataLine = sourceDataLine; } - } catch (LineUnavailableException e) { - causeException = e; - } catch (IllegalArgumentException e) { - causeException = e; - } catch (SecurityException e) { - causeException = e; - } - - if (causeException != null) { - if (isOpen()) + } catch (final LineUnavailableException | SecurityException + | IllegalArgumentException e) { + if (isOpen()) { close(); + } // am: need MidiUnavailableException(Throwable) ctor! MidiUnavailableException ex = new MidiUnavailableException( "Can not open line"); - ex.initCause(causeException); + ex.initCause(e); throw ex; } - } } diff --git a/jdk/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java b/jdk/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java index 1dbd72a262a..fd960395b1f 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java +++ b/jdk/src/java.desktop/share/classes/com/sun/media/sound/StandardMidiFileReader.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,27 +25,25 @@ package com.sun.media.sound; +import java.io.BufferedInputStream; import java.io.DataInputStream; +import java.io.EOFException; import java.io.File; import java.io.FileInputStream; -import java.io.InputStream; import java.io.IOException; -import java.io.EOFException; -import java.io.BufferedInputStream; +import java.io.InputStream; import java.net.URL; -import javax.sound.midi.MidiFileFormat; import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MetaMessage; import javax.sound.midi.MidiEvent; +import javax.sound.midi.MidiFileFormat; import javax.sound.midi.MidiMessage; import javax.sound.midi.Sequence; import javax.sound.midi.SysexMessage; import javax.sound.midi.Track; import javax.sound.midi.spi.MidiFileReader; - - /** * MIDI file reader. * @@ -53,19 +51,23 @@ import javax.sound.midi.spi.MidiFileReader; * @author Jan Borgersen * @author Florian Bomers */ - public final class StandardMidiFileReader extends MidiFileReader { private static final int MThd_MAGIC = 0x4d546864; // 'MThd' private static final int bisBufferSize = 1024; // buffer size in buffered input streams - public MidiFileFormat getMidiFileFormat(InputStream stream) throws InvalidMidiDataException, IOException { + public MidiFileFormat getMidiFileFormat(InputStream stream) + throws InvalidMidiDataException, IOException { return getMidiFileFormatFromStream(stream, MidiFileFormat.UNKNOWN_LENGTH, null); } - // $$fb 2002-04-17: part of fix for 4635286: MidiSystem.getMidiFileFormat() returns format having invalid length - private MidiFileFormat getMidiFileFormatFromStream(InputStream stream, int fileLength, SMFParser smfParser) throws InvalidMidiDataException, IOException { + // $$fb 2002-04-17: part of fix for 4635286: MidiSystem.getMidiFileFormat() + // returns format having invalid length + private MidiFileFormat getMidiFileFormatFromStream(InputStream stream, + int fileLength, + SMFParser smfParser) + throws InvalidMidiDataException, IOException{ int maxReadLength = 16; int duration = MidiFileFormat.UNKNOWN_LENGTH; DataInputStream dis; @@ -230,7 +232,7 @@ public final class StandardMidiFileReader extends MidiFileReader { //============================================================================================================= /** - * State variables during parsing of a MIDI file + * State variables during parsing of a MIDI file. */ final class SMFParser { private static final int MTrk_MAGIC = 0x4d54726b; // 'MTrk' @@ -297,7 +299,11 @@ final class SMFParser { } } // now read track in a byte array - trackData = new byte[trackLength]; + try { + trackData = new byte[trackLength]; + } catch (final OutOfMemoryError oom) { + throw new IOException("Track length too big", oom); + } try { // $$fb 2003-08-20: fix for 4910986: MIDI file parser breaks up on http connection stream.readFully(trackData); @@ -386,8 +392,13 @@ final class SMFParser { // meta int metaType = readUnsigned(); int metaLength = (int) readVarInt(); + final byte[] metaData; + try { + metaData = new byte[metaLength]; + } catch (final OutOfMemoryError oom) { + throw new IOException("Meta length too big", oom); + } - byte[] metaData = new byte[metaLength]; read(metaData); MetaMessage metaMessage = new MetaMessage(); @@ -413,5 +424,4 @@ final class SMFParser { throw new EOFException("invalid MIDI file"); } } - } diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ja.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ja.properties index c5314fa25a9..cf9507412fc 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ja.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ja.properties @@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic={0}\u306E\u540D\u524D\u3092\u5909\u66F4\ FileChooser.renameErrorFileExists.textAndMnemonic={0}\u306E\u540D\u524D\u3092\u5909\u66F4\u3067\u304D\u307E\u305B\u3093: \u6307\u5B9A\u3057\u305F\u540D\u524D\u306E\u30D5\u30A1\u30A4\u30EB\u306F\u3059\u3067\u306B\u5B58\u5728\u3057\u307E\u3059\u3002\u5225\u306E\u30D5\u30A1\u30A4\u30EB\u540D\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002 FileChooser.acceptAllFileFilter.textAndMnemonic=\u3059\u3079\u3066\u306E\u30D5\u30A1\u30A4\u30EB FileChooser.cancelButton.textAndMnemonic=\u53D6\u6D88 -FileChooser.saveButton.textAndMnemonic=\u4FDD\u5B58(&S) -FileChooser.openButton.textAndMnemonic=\u958B\u304F(&O) +FileChooser.saveButton.textAndMnemonic=\u4FDD\u5B58 +FileChooser.openButton.textAndMnemonic=\u958B\u304F FileChooser.saveDialogTitle.textAndMnemonic=\u4FDD\u5B58 FileChooser.openDialogTitle.textAndMnemonic=\u958B\u304F FileChooser.updateButton.textAndMnemonic=\u66F4\u65B0(&U) FileChooser.helpButton.textAndMnemonic=\u30D8\u30EB\u30D7(&H) -FileChooser.directoryOpenButton.textAndMnemonic=\u958B\u304F(&O) +FileChooser.directoryOpenButton.textAndMnemonic=\u958B\u304F # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties index 7f313031ba2..c8e67dfa5fa 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_ko.properties @@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic={0}\uC758 \uC774\uB984\uC744 \uBC14\uAFC FileChooser.renameErrorFileExists.textAndMnemonic={0}\uC758 \uC774\uB984\uC744 \uBC14\uAFC0 \uC218 \uC5C6\uC74C: \uC9C0\uC815\uD55C \uC774\uB984\uC744 \uC0AC\uC6A9\uD558\uB294 \uD30C\uC77C\uC774 \uC874\uC7AC\uD569\uB2C8\uB2E4. \uB2E4\uB978 \uD30C\uC77C \uC774\uB984\uC744 \uC9C0\uC815\uD558\uC2ED\uC2DC\uC624. FileChooser.acceptAllFileFilter.textAndMnemonic=\uBAA8\uB4E0 \uD30C\uC77C FileChooser.cancelButton.textAndMnemonic=\uCDE8\uC18C -FileChooser.saveButton.textAndMnemonic=\uC800\uC7A5(&S) -FileChooser.openButton.textAndMnemonic=\uC5F4\uAE30(&O) +FileChooser.saveButton.textAndMnemonic=\uC800\uC7A5 +FileChooser.openButton.textAndMnemonic=\uC5F4\uAE30 FileChooser.saveDialogTitle.textAndMnemonic=\uC800\uC7A5 FileChooser.openDialogTitle.textAndMnemonic=\uC5F4\uAE30 FileChooser.updateButton.textAndMnemonic=\uC5C5\uB370\uC774\uD2B8(&U) FileChooser.helpButton.textAndMnemonic=\uB3C4\uC6C0\uB9D0(&H) -FileChooser.directoryOpenButton.textAndMnemonic=\uC5F4\uAE30(&O) +FileChooser.directoryOpenButton.textAndMnemonic=\uC5F4\uAE30 # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.properties index d4c357281f4..ab3bb26933a 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_CN.properties @@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=\u65E0\u6CD5\u91CD\u547D\u540D{0} FileChooser.renameErrorFileExists.textAndMnemonic=\u65E0\u6CD5\u91CD\u547D\u540D{0}: \u5DF2\u5B58\u5728\u5177\u6709\u6240\u6307\u5B9A\u540D\u79F0\u7684\u6587\u4EF6\u3002\u8BF7\u6307\u5B9A\u5176\u4ED6\u6587\u4EF6\u540D\u3002 FileChooser.acceptAllFileFilter.textAndMnemonic=\u6240\u6709\u6587\u4EF6 FileChooser.cancelButton.textAndMnemonic=\u53D6\u6D88 -FileChooser.saveButton.textAndMnemonic=\u4FDD\u5B58(&S) -FileChooser.openButton.textAndMnemonic=\u6253\u5F00(&O) +FileChooser.saveButton.textAndMnemonic=\u4FDD\u5B58 +FileChooser.openButton.textAndMnemonic=\u6253\u5F00 FileChooser.saveDialogTitle.textAndMnemonic=\u4FDD\u5B58 FileChooser.openDialogTitle.textAndMnemonic=\u6253\u5F00 FileChooser.updateButton.textAndMnemonic=\u66F4\u65B0(&U) FileChooser.helpButton.textAndMnemonic=\u5E2E\u52A9(&H) -FileChooser.directoryOpenButton.textAndMnemonic=\u6253\u5F00(&O) +FileChooser.directoryOpenButton.textAndMnemonic=\u6253\u5F00 # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.properties b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.properties index 654166173c7..d4b47957a77 100644 --- a/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.properties +++ b/jdk/src/java.desktop/share/classes/com/sun/swing/internal/plaf/basic/resources/basic_zh_TW.properties @@ -42,13 +42,13 @@ FileChooser.renameError.textAndMnemonic=\u7121\u6CD5\u91CD\u65B0\u547D\u540D {0} FileChooser.renameErrorFileExists.textAndMnemonic=\u7121\u6CD5\u91CD\u65B0\u547D\u540D {0}: \u5DF2\u7D93\u5B58\u5728\u60A8\u6240\u6307\u5B9A\u540D\u7A31\u7684\u6A94\u6848\u3002\u8ACB\u6307\u5B9A\u4E0D\u540C\u7684\u540D\u7A31\u3002 FileChooser.acceptAllFileFilter.textAndMnemonic=\u6240\u6709\u6A94\u6848 FileChooser.cancelButton.textAndMnemonic=\u53D6\u6D88 -FileChooser.saveButton.textAndMnemonic=\u5132\u5B58(&S) -FileChooser.openButton.textAndMnemonic=\u958B\u555F(&O) +FileChooser.saveButton.textAndMnemonic=\u5132\u5B58 +FileChooser.openButton.textAndMnemonic=\u958B\u555F FileChooser.saveDialogTitle.textAndMnemonic=\u5132\u5B58 FileChooser.openDialogTitle.textAndMnemonic=\u958B\u555F FileChooser.updateButton.textAndMnemonic=\u66F4\u65B0(&U) FileChooser.helpButton.textAndMnemonic=\u8AAA\u660E(&H) -FileChooser.directoryOpenButton.textAndMnemonic=\u958B\u555F(&O) +FileChooser.directoryOpenButton.textAndMnemonic=\u958B\u555F # File Size Units FileChooser.fileSizeKiloBytes={0} KB diff --git a/jdk/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java b/jdk/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java index 89abeca03d6..e916dace8a3 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java +++ b/jdk/src/java.desktop/share/classes/java/awt/color/ICC_Profile.java @@ -968,20 +968,22 @@ public class ICC_Profile implements Serializable { */ public static ICC_Profile getInstance(String fileName) throws IOException { ICC_Profile thisProfile; - FileInputStream fis = null; + InputStream is = null; File f = getProfileFile(fileName); if (f != null) { - fis = new FileInputStream(f); + is = new FileInputStream(f); + } else { + is = getStandardProfileInputStream(fileName); } - if (fis == null) { + if (is == null) { throw new IOException("Cannot open file " + fileName); } - thisProfile = getInstance(fis); + thisProfile = getInstance(is); - fis.close(); /* close the file */ + is.close(); /* close the file */ return thisProfile; } @@ -1086,28 +1088,17 @@ public class ICC_Profile implements Serializable { void activateDeferredProfile() throws ProfileDataException { byte profileData[]; - FileInputStream fis; final String fileName = deferralInfo.filename; profileActivator = null; deferralInfo = null; - PrivilegedAction pa = new PrivilegedAction() { - public FileInputStream run() { - File f = getStandardProfileFile(fileName); - if (f != null) { - try { - return new FileInputStream(f); - } catch (FileNotFoundException e) {} - } - return null; - } - }; - if ((fis = AccessController.doPrivileged(pa)) == null) { + InputStream is = getStandardProfileInputStream(fileName); + if (is == null) { throw new ProfileDataException("Cannot open file " + fileName); } try { - profileData = getProfileDataFromStream(fis); - fis.close(); /* close the file */ + profileData = getProfileDataFromStream(is); + is.close(); /* close the file */ } catch (IOException e) { ProfileDataException pde = new @@ -1810,10 +1801,12 @@ public class ICC_Profile implements Serializable { * fileName may be an absolute or a relative file specification. * Relative file names are looked for in several places: first, relative * to any directories specified by the java.iccprofile.path property; - * second, relative to any directories specified by the java.class.path - * property; finally, in a directory used to store profiles always - * available, such as a profile for sRGB. Built-in profiles use .pf as - * the file name extension for profiles, e.g. sRGB.pf. + * second, relative to any directories specified by the java.class.path. + * The built-in profile files are now loaded as resources, since they + * may not be individual disk files, and so this method will not find + * these and on a null return, the caller needs to try as resources. + * Built-in profiles use .pf as the file name extension for profiles, + * e.g. sRGB.pf. */ private static File getProfileFile(String fileName) { String path, dir, fullPath; @@ -1849,30 +1842,22 @@ public class ICC_Profile implements Serializable { fullPath = dir + File.separatorChar + fileName; f = new File(fullPath); } - } + } - if ((f == null) || (!f.isFile())) { - /* try the directory of built-in profiles */ - f = getStandardProfileFile(fileName); + if (f != null && !f.isFile()) { + f = null; } - if (f != null && f.isFile()) { - return f; - } - return null; + return f; } /** - * Returns a file object corresponding to a built-in profile + * Returns a stream corresponding to a built-in profile * specified by fileName. * If there is no built-in profile with such name, then the method * returns null. */ - private static File getStandardProfileFile(String fileName) { - String dir = System.getProperty("java.home") + - File.separatorChar + "lib" + File.separatorChar + "cmm"; - String fullPath = dir + File.separatorChar + fileName; - File f = new File(fullPath); - return (f.isFile() && isChildOf(f, dir)) ? f : null; + private static InputStream getStandardProfileInputStream(String fileName) { + return PCMM.class.getResourceAsStream("profiles/" + fileName); } /** @@ -1901,7 +1886,7 @@ public class ICC_Profile implements Serializable { private static boolean standardProfileExists(final String fileName) { return AccessController.doPrivileged(new PrivilegedAction() { public Boolean run() { - return getStandardProfileFile(fileName) != null; + return PCMM.class.getResource("profiles/"+fileName) != null; } }); } diff --git a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/Clipboard.java b/jdk/src/java.desktop/share/classes/java/awt/datatransfer/Clipboard.java index 210c700941e..6211692d5c9 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/Clipboard.java +++ b/jdk/src/java.desktop/share/classes/java/awt/datatransfer/Clipboard.java @@ -25,7 +25,7 @@ package java.awt.datatransfer; -import java.awt.EventQueue; +import sun.datatransfer.DataFlavorUtil; import java.util.Objects; import java.util.Set; @@ -130,7 +130,8 @@ public class Clipboard { this.contents = contents; if (oldOwner != null && oldOwner != owner) { - EventQueue.invokeLater(() -> oldOwner.lostOwnership(Clipboard.this, oldContents)); + DataFlavorUtil.getDesktopService().invokeOnEventThread(() -> + oldOwner.lostOwnership(Clipboard.this, oldContents)); } fireFlavorsChanged(); } @@ -324,7 +325,7 @@ public class Clipboard { return; } flavorListeners.forEach(listener -> - EventQueue.invokeLater(() -> + DataFlavorUtil.getDesktopService().invokeOnEventThread(() -> listener.flavorsChanged(new FlavorEvent(Clipboard.this)))); } diff --git a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/DataFlavor.java b/jdk/src/java.desktop/share/classes/java/awt/datatransfer/DataFlavor.java index 57132f2f53e..84b18fc332a 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/DataFlavor.java +++ b/jdk/src/java.desktop/share/classes/java/awt/datatransfer/DataFlavor.java @@ -25,7 +25,7 @@ package java.awt.datatransfer; -import sun.awt.datatransfer.DataTransferer; +import sun.datatransfer.DataFlavorUtil; import sun.reflect.misc.ReflectUtil; import java.io.ByteArrayInputStream; @@ -44,7 +44,6 @@ import java.nio.ByteBuffer; import java.nio.CharBuffer; import java.util.Arrays; import java.util.Collections; -import java.util.Comparator; import java.util.Objects; import static sun.security.util.SecurityConstants.GET_CLASSLOADER_PERMISSION; @@ -582,12 +581,12 @@ public class DataFlavor implements Externalizable, Cloneable { } else { params += representationClass.getName(); } - if (DataTransferer.isFlavorCharsetTextType(this) && + if (DataFlavorUtil.isFlavorCharsetTextType(this) && (isRepresentationClassInputStream() || isRepresentationClassByteBuffer() || byte[].class.equals(representationClass))) { - params += ";charset=" + DataTransferer.getTextCharset(this); + params += ";charset=" + DataFlavorUtil.getTextCharset(this); } return params; } @@ -609,13 +608,8 @@ public class DataFlavor implements Externalizable, Cloneable { * @since 1.3 */ public static final DataFlavor getTextPlainUnicodeFlavor() { - String encoding = null; - DataTransferer transferer = DataTransferer.getInstance(); - if (transferer != null) { - encoding = transferer.getDefaultUnicodeEncoding(); - } return new DataFlavor( - "text/plain;charset="+encoding + "text/plain;charset=" + DataFlavorUtil.getDesktopService().getDefaultUnicodeEncoding() +";class=java.io.InputStream", "Plain Text"); } @@ -741,12 +735,8 @@ public class DataFlavor implements Externalizable, Cloneable { return null; } - if (textFlavorComparator == null) { - textFlavorComparator = new TextFlavorComparator(); - } - DataFlavor bestFlavor = Collections.max(Arrays.asList(availableFlavors), - textFlavorComparator); + DataFlavorUtil.getTextFlavorComparator()); if (!bestFlavor.isFlavorTextType()) { return null; @@ -755,46 +745,6 @@ public class DataFlavor implements Externalizable, Cloneable { return bestFlavor; } - private static Comparator textFlavorComparator; - - static class TextFlavorComparator - extends DataTransferer.DataFlavorComparator { - - /** - * Compares two DataFlavor objects. Returns a negative - * integer, zero, or a positive integer as the first - * DataFlavor is worse than, equal to, or better than the - * second. - *

    - * DataFlavors are ordered according to the rules outlined - * for selectBestTextFlavor. - * - * @param flavor1 the first DataFlavor to be compared - * @param flavor2 the second DataFlavor to be compared - * @return a negative integer, zero, or a positive integer as the first - * argument is worse, equal to, or better than the second - * @throws ClassCastException if either of the arguments is not an - * instance of DataFlavor - * @throws NullPointerException if either of the arguments is - * null - * - * @see #selectBestTextFlavor - */ - public int compare(DataFlavor flavor1, DataFlavor flavor2) { - if (flavor1.isFlavorTextType()) { - if (flavor2.isFlavorTextType()) { - return super.compare(flavor1, flavor2); - } else { - return 1; - } - } else if (flavor2.isFlavorTextType()) { - return -1; - } else { - return 0; - } - } - } - /** * Gets a Reader for a text flavor, decoded, if necessary, for the expected * charset (encoding). The supported representation classes are @@ -1015,13 +965,13 @@ public class DataFlavor implements Externalizable, Cloneable { } if ("text".equals(getPrimaryType())) { - if (DataTransferer.doesSubtypeSupportCharset(this) + if (DataFlavorUtil.doesSubtypeSupportCharset(this) && representationClass != null && !isStandardTextRepresentationClass()) { String thisCharset = - DataTransferer.canonicalName(this.getParameter("charset")); + DataFlavorUtil.canonicalName(this.getParameter("charset")); String thatCharset = - DataTransferer.canonicalName(that.getParameter("charset")); + DataFlavorUtil.canonicalName(that.getParameter("charset")); if (!Objects.equals(thisCharset, thatCharset)) { return false; } @@ -1088,10 +1038,10 @@ public class DataFlavor implements Externalizable, Cloneable { // subTypes is '*', regardless of the other subType. if ("text".equals(primaryType)) { - if (DataTransferer.doesSubtypeSupportCharset(this) + if (DataFlavorUtil.doesSubtypeSupportCharset(this) && representationClass != null && !isStandardTextRepresentationClass()) { - String charset = DataTransferer.canonicalName(getParameter("charset")); + String charset = DataFlavorUtil.canonicalName(getParameter("charset")); if (charset != null) { total += charset.hashCode(); } @@ -1280,9 +1230,8 @@ public class DataFlavor implements Externalizable, Cloneable { * Returns true if the representation class is Remote. * @return true if the representation class is Remote */ - public boolean isRepresentationClassRemote() { - return DataTransferer.isRemote(representationClass); + return DataFlavorUtil.RMI.isRemote(representationClass); } /** @@ -1356,8 +1305,8 @@ public class DataFlavor implements Externalizable, Cloneable { * @since 1.4 */ public boolean isFlavorTextType() { - return (DataTransferer.isFlavorCharsetTextType(this) || - DataTransferer.isFlavorNoncharsetTextType(this)); + return (DataFlavorUtil.isFlavorCharsetTextType(this) || + DataFlavorUtil.isFlavorNoncharsetTextType(this)); } /** diff --git a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/SystemFlavorMap.java b/jdk/src/java.desktop/share/classes/java/awt/datatransfer/SystemFlavorMap.java index e799020110a..8bd47fe5f45 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/datatransfer/SystemFlavorMap.java +++ b/jdk/src/java.desktop/share/classes/java/awt/datatransfer/SystemFlavorMap.java @@ -25,22 +25,15 @@ package java.awt.datatransfer; -import java.awt.Toolkit; - -import java.io.BufferedInputStream; -import java.io.InputStream; -import java.lang.ref.SoftReference; +import sun.datatransfer.DataFlavorUtil; +import sun.datatransfer.DesktopDatatransferService; import java.io.BufferedReader; -import java.io.File; -import java.io.InputStreamReader; import java.io.IOException; - -import java.net.URL; -import java.net.MalformedURLException; - +import java.io.InputStream; +import java.io.InputStreamReader; +import java.lang.ref.SoftReference; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; @@ -48,12 +41,8 @@ import java.util.LinkedHashSet; import java.util.List; import java.util.Map; import java.util.Objects; -import java.util.Properties; import java.util.Set; -import sun.awt.AppContext; -import sun.awt.datatransfer.DataTransferer; - /** * The SystemFlavorMap is a configurable map between "natives" (Strings), which * correspond to platform-specific data formats, and "flavors" (DataFlavors), @@ -73,13 +62,6 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { private static final Object FLAVOR_MAP_KEY = new Object(); - /** - * Copied from java.util.Properties. - */ - private static final String keyValueSeparators = "=: \t\r\n\f"; - private static final String strictKeyValueSeparators = "=:"; - private static final String whiteSpaceChars = " \t\r\n\f"; - /** * The list of valid, decoded text flavor representation classes, in order * from best to worst. @@ -198,16 +180,11 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { /** * Returns the default FlavorMap for this thread's ClassLoader. + * * @return the default FlavorMap for this thread's ClassLoader */ public static FlavorMap getDefaultFlavorMap() { - AppContext context = AppContext.getAppContext(); - FlavorMap fm = (FlavorMap) context.get(FLAVOR_MAP_KEY); - if (fm == null) { - fm = new SystemFlavorMap(); - context.put(FLAVOR_MAP_KEY, fm); - } - return fm; + return DataFlavorUtil.getDesktopService().getFlavorMap(SystemFlavorMap::new); } private SystemFlavorMap() { @@ -223,7 +200,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } isMapInitialized = true; - InputStream is = SystemFlavorMap.class.getResourceAsStream("/sun/awt/datatransfer/flavormap.properties"); + InputStream is = SystemFlavorMap.class.getResourceAsStream("/sun/datatransfer/resources/flavormap.properties"); if (is == null) { throw new InternalError("Default flavor mapping not found"); } @@ -238,22 +215,25 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { line = line.substring(0, line.length() - 1) + reader.readLine().trim(); } int delimiterPosition = line.indexOf('='); - String key = line.substring(0, delimiterPosition).replace("\\ ", " "); + String key = line.substring(0, delimiterPosition).replaceAll("\\ ", " "); String[] values = line.substring(delimiterPosition + 1, line.length()).split(","); for (String value : values) { try { + value = loadConvert(value); MimeType mime = new MimeType(value); if ("text".equals(mime.getPrimaryType())) { String charset = mime.getParameter("charset"); - if (DataTransferer.doesSubtypeSupportCharset(mime.getSubType(), charset)) + if (DataFlavorUtil.doesSubtypeSupportCharset(mime.getSubType(), charset)) { // We need to store the charset and eoln // parameters, if any, so that the // DataTransferer will have this information // for conversion into the native format. - DataTransferer transferer = DataTransferer.getInstance(); - if (transferer != null) { - transferer.registerTextFlavorProperties(key, charset, + DesktopDatatransferService desktopService = + DataFlavorUtil.getDesktopService(); + if (desktopService.isDesktopPresent()) { + desktopService.registerTextFlavorProperties( + key, charset, mime.getParameter("eoln"), mime.getParameter("terminators")); } @@ -305,6 +285,63 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } } + // Copied from java.util.Properties + private static String loadConvert(String theString) { + char aChar; + int len = theString.length(); + StringBuilder outBuffer = new StringBuilder(len); + + for (int x = 0; x < len; ) { + aChar = theString.charAt(x++); + if (aChar == '\\') { + aChar = theString.charAt(x++); + if (aChar == 'u') { + // Read the xxxx + int value = 0; + for (int i = 0; i < 4; i++) { + aChar = theString.charAt(x++); + switch (aChar) { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + value = (value << 4) + aChar - '0'; + break; + } + case 'a': case 'b': case 'c': + case 'd': case 'e': case 'f': { + value = (value << 4) + 10 + aChar - 'a'; + break; + } + case 'A': case 'B': case 'C': + case 'D': case 'E': case 'F': { + value = (value << 4) + 10 + aChar - 'A'; + break; + } + default: { + throw new IllegalArgumentException( + "Malformed \\uxxxx encoding."); + } + } + } + outBuffer.append((char)value); + } else { + if (aChar == 't') { + aChar = '\t'; + } else if (aChar == 'r') { + aChar = '\r'; + } else if (aChar == 'n') { + aChar = '\n'; + } else if (aChar == 'f') { + aChar = '\f'; + } + outBuffer.append(aChar); + } + } else { + outBuffer.append(aChar); + } + } + return outBuffer.toString(); + } + /** * Stores the listed object under the specified hash key in map. Unlike a * standard map, the listed object will not replace any object already at @@ -332,10 +369,10 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { LinkedHashSet flavors = getNativeToFlavor().get(nat); if (nat != null && !disabledMappingGenerationKeys.contains(nat)) { - DataTransferer transferer = DataTransferer.getInstance(); - if (transferer != null) { + DesktopDatatransferService desktopService = DataFlavorUtil.getDesktopService(); + if (desktopService.isDesktopPresent()) { LinkedHashSet platformFlavors = - transferer.getPlatformMappingsForNative(nat); + desktopService.getPlatformMappingsForNative(nat); if (!platformFlavors.isEmpty()) { if (flavors != null) { // Prepending the platform-specific mappings ensures @@ -395,10 +432,10 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { LinkedHashSet natives = getFlavorToNative().get(flav); if (flav != null && !disabledMappingGenerationKeys.contains(flav)) { - DataTransferer transferer = DataTransferer.getInstance(); - if (transferer != null) { + DesktopDatatransferService desktopService = DataFlavorUtil.getDesktopService(); + if (desktopService.isDesktopPresent()) { LinkedHashSet platformNatives = - transferer.getPlatformMappingsForFlavor(flav); + desktopService.getPlatformMappingsForFlavor(flav); if (!platformNatives.isEmpty()) { if (natives != null) { // Prepend the platform-specific mappings to ensure @@ -474,7 +511,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { // In this case we shouldn't synthesize a native for this flavor, // since its mappings were explicitly specified. retval = flavorToNativeLookup(flav, false); - } else if (DataTransferer.isFlavorCharsetTextType(flav)) { + } else if (DataFlavorUtil.isFlavorCharsetTextType(flav)) { retval = new LinkedHashSet<>(0); // For text/* flavors, flavor-to-native mappings specified in @@ -502,7 +539,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { // addUnencodedNativeForFlavor(), so they have lower priority. retval.addAll(flavorToNativeLookup(flav, false)); } - } else if (DataTransferer.isFlavorNoncharsetTextType(flav)) { + } else if (DataFlavorUtil.isFlavorNoncharsetTextType(flav)) { retval = getTextTypeToNative().get(flav.mimeType.getBaseType()); if (retval == null || retval.isEmpty()) { @@ -602,7 +639,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { // on load from flavormap.properties. } - if (DataTransferer.doesSubtypeSupportCharset(subType, null)) { + if (DataFlavorUtil.doesSubtypeSupportCharset(subType, null)) { if (TEXT_PLAIN_BASE_TYPE.equals(baseType)) { returnValue.add(DataFlavor.stringFlavor); @@ -624,7 +661,7 @@ public final class SystemFlavorMap implements FlavorMap, FlavorTable { } } - for (String charset : DataTransferer.standardEncodings()) { + for (String charset : DataFlavorUtil.standardEncodings()) { for (String encodedTextClass : ENCODED_TEXT_CLASSES) { final String mimeType = diff --git a/jdk/src/java.desktop/share/classes/java/awt/font/TextLayout.java b/jdk/src/java.desktop/share/classes/java/awt/font/TextLayout.java index 45da5af89c6..f86779c161b 100644 --- a/jdk/src/java.desktop/share/classes/java/awt/font/TextLayout.java +++ b/jdk/src/java.desktop/share/classes/java/awt/font/TextLayout.java @@ -1811,7 +1811,7 @@ public final class TextLayout implements Cloneable { * should be logical or visual counterparts. They are not * checked for validity. */ - private final TextHitInfo getStrongHit(TextHitInfo hit1, TextHitInfo hit2) { + private TextHitInfo getStrongHit(TextHitInfo hit1, TextHitInfo hit2) { // right now we're using the following rule for strong hits: // A hit on a character with a lower level diff --git a/jdk/src/java.desktop/share/classes/java/beans/PropertyChangeSupport.java b/jdk/src/java.desktop/share/classes/java/beans/PropertyChangeSupport.java index 40e58ae1e5d..532fdea1edc 100644 --- a/jdk/src/java.desktop/share/classes/java/beans/PropertyChangeSupport.java +++ b/jdk/src/java.desktop/share/classes/java/beans/PropertyChangeSupport.java @@ -544,7 +544,7 @@ public class PropertyChangeSupport implements Serializable { /** * {@inheritDoc} */ - public final PropertyChangeListener extract(PropertyChangeListener listener) { + public PropertyChangeListener extract(PropertyChangeListener listener) { while (listener instanceof PropertyChangeListenerProxy) { listener = ((PropertyChangeListenerProxy) listener).getListener(); } diff --git a/jdk/src/java.desktop/share/classes/java/beans/VetoableChangeSupport.java b/jdk/src/java.desktop/share/classes/java/beans/VetoableChangeSupport.java index 14902cc6276..6f211378991 100644 --- a/jdk/src/java.desktop/share/classes/java/beans/VetoableChangeSupport.java +++ b/jdk/src/java.desktop/share/classes/java/beans/VetoableChangeSupport.java @@ -533,7 +533,7 @@ public class VetoableChangeSupport implements Serializable { /** * {@inheritDoc} */ - public final VetoableChangeListener extract(VetoableChangeListener listener) { + public VetoableChangeListener extract(VetoableChangeListener listener) { while (listener instanceof VetoableChangeListenerProxy) { listener = ((VetoableChangeListenerProxy) listener).getListener(); } diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java b/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java index 1ff7c219e2d..553f733514c 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/ImageReader.java @@ -2806,7 +2806,7 @@ public abstract class ImageReader { * @param imageTypes an Iterator of * ImageTypeSpecifiers indicating the legal image * types, with the default first. - * @param width the true width of the image or tile begin decoded. + * @param width the true width of the image or tile being decoded. * @param height the true width of the image or tile being decoded. * * @return the BufferedImage to which decoded pixel diff --git a/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java b/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java index b939a2c0e5f..99723915972 100644 --- a/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java +++ b/jdk/src/java.desktop/share/classes/javax/imageio/metadata/IIOMetadataNode.java @@ -305,6 +305,9 @@ public class IIOMetadataNode implements Element, NodeList { /** * Check that the node is either null or an * IIOMetadataNode. + * + * @throws DOMException if {@code node} is not {@code null} and not an + * instance of {@code IIOMetadataNode} */ private void checkNode(Node node) throws DOMException { if (node == null) { diff --git a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DialogTypeSelection.java b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DialogTypeSelection.java index 5d1948e22fc..3e567f50973 100644 --- a/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DialogTypeSelection.java +++ b/jdk/src/java.desktop/share/classes/javax/print/attribute/standard/DialogTypeSelection.java @@ -67,7 +67,7 @@ public final class DialogTypeSelection extends EnumSyntax COMMON = new DialogTypeSelection(1); /** - * Construct a new dialog type selection enumeration value with the + * Constructs a new dialog type selection enumeration value with the * given integer value. * * @param value Integer value. @@ -101,7 +101,7 @@ public final class DialogTypeSelection extends EnumSyntax /** - * Get the printing attribute class which is to be used as the "category" + * Gets the printing attribute class which is to be used as the "category" * for this printing attribute value. *

    * For class DialogTypeSelection the category is class @@ -116,7 +116,7 @@ public final class DialogTypeSelection extends EnumSyntax /** - * Get the name of the category of which this attribute value is an + * Gets the name of the category of which this attribute value is an * instance. *

    * For class DialogTypeSelection the category name is diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/ControllerEventListener.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/ControllerEventListener.java index c9666bc2df8..dba4e80c54d 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/ControllerEventListener.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/ControllerEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -27,38 +27,35 @@ package javax.sound.midi; import java.util.EventListener; - /** - * The ControllerEventListener interface should be implemented - * by classes whose instances need to be notified when a Sequencer - * has processed a requested type of MIDI control-change event. - * To register a ControllerEventListener object to receive such - * notifications, invoke the + * The {@code ControllerEventListener} interface should be implemented by + * classes whose instances need to be notified when a {@link Sequencer} has + * processed a requested type of MIDI control-change event. To register a + * {@code ControllerEventListener} object to receive such notifications, invoke + * the * {@link Sequencer#addControllerEventListener(ControllerEventListener, int[]) - * addControllerEventListener} method of Sequencer, - * specifying the types of MIDI controllers about which you are interested in - * getting control-change notifications. - * - * @see MidiChannel#controlChange(int, int) + * addControllerEventListener} method of {@code Sequencer}, specifying the types + * of MIDI controllers about which you are interested in getting control-change + * notifications. * * @author Kara Kytle + * @see MidiChannel#controlChange(int, int) */ public interface ControllerEventListener extends EventListener { /** - * Invoked when a Sequencer has encountered and processed - * a control-change event of interest to this listener. The event passed - * in is a ShortMessage whose first data byte indicates - * the controller number and whose second data byte is the value to which - * the controller was set. - * - * @param event the control-change event that the sequencer encountered in - * the sequence it is processing + * Invoked when a {@link Sequencer} has encountered and processed a + * control-change event of interest to this listener. The event passed in is + * a {@code ShortMessage} whose first data byte indicates the controller + * number and whose second data byte is the value to which the controller + * was set. * + * @param event the control-change event that the sequencer encountered in + * the sequence it is processing * @see Sequencer#addControllerEventListener(ControllerEventListener, int[]) * @see MidiChannel#controlChange(int, int) * @see ShortMessage#getData1 * @see ShortMessage#getData2 */ - public void controlChange(ShortMessage event); + void controlChange(ShortMessage event); } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/Instrument.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/Instrument.java index 3255aeff033..8bda9676df2 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/Instrument.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/Instrument.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,49 +25,41 @@ package javax.sound.midi; -import java.net.URL; - - - /** - * An instrument is a sound-synthesis algorithm with certain parameter - * settings, usually designed to emulate a specific real-world - * musical instrument or to achieve a specific sort of sound effect. - * Instruments are typically stored in collections called soundbanks. - * Before the instrument can be used to play notes, it must first be loaded - * onto a synthesizer, and then it must be selected for use on - * one or more channels, via a program-change command. MIDI notes - * that are subsequently received on those channels will be played using + * An instrument is a sound-synthesis algorithm with certain parameter settings, + * usually designed to emulate a specific real-world musical instrument or to + * achieve a specific sort of sound effect. Instruments are typically stored in + * collections called soundbanks. Before the instrument can be used to play + * notes, it must first be loaded onto a synthesizer, and then it must be + * selected for use on one or more channels, via a program-change command. MIDI + * notes that are subsequently received on those channels will be played using * the sound of the selected instrument. * + * @author Kara Kytle * @see Soundbank * @see Soundbank#getInstruments * @see Patch * @see Synthesizer#loadInstrument(Instrument) * @see MidiChannel#programChange(int, int) - * @author Kara Kytle */ - public abstract class Instrument extends SoundbankResource { - /** - * Instrument patch + * Instrument patch. */ private final Patch patch; - /** - * Constructs a new MIDI instrument from the specified Patch. - * When a subsequent request is made to load the - * instrument, the sound bank will search its contents for this instrument's Patch, - * and the instrument will be loaded into the synthesizer at the - * bank and program location indicated by the Patch object. - * @param soundbank sound bank containing the instrument - * @param patch the patch of this instrument - * @param name the name of this instrument - * @param dataClass the class used to represent the sample's data. + * Constructs a new MIDI instrument from the specified {@code Patch}. When a + * subsequent request is made to load the instrument, the sound bank will + * search its contents for this instrument's {@code Patch}, and the + * instrument will be loaded into the synthesizer at the bank and program + * location indicated by the {@code Patch} object. * + * @param soundbank sound bank containing the instrument + * @param patch the patch of this instrument + * @param name the name of this instrument + * @param dataClass the class used to represent the sample's data * @see Synthesizer#loadInstrument(Instrument) */ protected Instrument(Soundbank soundbank, Patch patch, String name, Class dataClass) { @@ -76,10 +68,10 @@ public abstract class Instrument extends SoundbankResource { this.patch = patch; } - /** - * Obtains the Patch object that indicates the bank and program + * Obtains the {@code Patch} object that indicates the bank and program * numbers where this instrument is to be stored in the synthesizer. + * * @return this instrument's patch */ public Patch getPatch() { diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/InvalidMidiDataException.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/InvalidMidiDataException.java index ed20121fab8..28a75deefc4 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/InvalidMidiDataException.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/InvalidMidiDataException.java @@ -25,25 +25,25 @@ package javax.sound.midi; - /** - * An InvalidMidiDataException indicates that inappropriate MIDI - * data was encountered. This often means that the data is invalid in and of - * itself, from the perspective of the MIDI specification. An example would - * be an undefined status byte. However, the exception might simply - * mean that the data was invalid in the context it was used, or that - * the object to which the data was given was unable to parse or use it. - * For example, a file reader might not be able to parse a Type 2 MIDI file, even - * though that format is defined in the MIDI specification. + * An {@code InvalidMidiDataException} indicates that inappropriate MIDI data + * was encountered. This often means that the data is invalid in and of itself, + * from the perspective of the MIDI specification. An example would be an + * undefined status byte. However, the exception might simply mean that the data + * was invalid in the context it was used, or that the object to which the data + * was given was unable to parse or use it. For example, a file reader might not + * be able to parse a Type 2 MIDI file, even though that format is defined in + * the MIDI specification. * * @author Kara Kytle */ public class InvalidMidiDataException extends Exception { + private static final long serialVersionUID = 2780771756789932067L; /** - * Constructs an InvalidMidiDataException with - * null for its error detail message. + * Constructs an {@code InvalidMidiDataException} with {@code null} for its + * error detail message. */ public InvalidMidiDataException() { @@ -51,10 +51,10 @@ public class InvalidMidiDataException extends Exception { } /** - * Constructs an InvalidMidiDataException with the - * specified detail message. + * Constructs an {@code InvalidMidiDataException} with the specified detail + * message. * - * @param message the string to display as an error detail message + * @param message the string to display as an error detail message */ public InvalidMidiDataException(String message) { diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MetaEventListener.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MetaEventListener.java index 94fe3d8044f..6f431bf22c9 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MetaEventListener.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MetaEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -27,24 +27,23 @@ package javax.sound.midi; import java.util.EventListener; - /** - * The MetaEventListener interface should be implemented - * by classes whose instances need to be notified when a {@link Sequencer} - * has processed a {@link MetaMessage}. - * To register a MetaEventListener object to receive such - * notifications, pass it as the argument to the - * {@link Sequencer#addMetaEventListener(MetaEventListener) addMetaEventListener} - * method of Sequencer. + * The {@code MetaEventListener} interface should be implemented by classes + * whose instances need to be notified when a {@link Sequencer} has processed a + * {@link MetaMessage}. To register a {@code MetaEventListener} object to + * receive such notifications, pass it as the argument to the + * {@link Sequencer#addMetaEventListener(MetaEventListener) + * addMetaEventListener} method of {@code Sequencer}. * * @author Kara Kytle */ public interface MetaEventListener extends EventListener { /** - * Invoked when a {@link Sequencer} has encountered and processed - * a MetaMessage in the {@link Sequence} it is processing. - * @param meta the meta-message that the sequencer encountered + * Invoked when a {@link Sequencer} has encountered and processed a + * {@code MetaMessage} in the {@code Sequence} it is processing. + * + * @param meta the meta-message that the sequencer encountered */ - public void meta(MetaMessage meta); + void meta(MetaMessage meta); } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MetaMessage.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MetaMessage.java index 6378435acc7..2e73cc37ddf 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MetaMessage.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MetaMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,65 +25,54 @@ package javax.sound.midi; - /** - * A MetaMessage is a {@link MidiMessage} that is not meaningful to synthesizers, but - * that can be stored in a MIDI file and interpreted by a sequencer program. - * (See the discussion in the MidiMessage - * class description.) The Standard MIDI Files specification defines - * various types of meta-events, such as sequence number, lyric, cue point, - * and set tempo. There are also meta-events - * for such information as lyrics, copyrights, tempo indications, time and key - * signatures, markers, etc. For more information, see the Standard MIDI Files 1.0 - * specification, which is part of the Complete MIDI 1.0 Detailed Specification - * published by the MIDI Manufacturer's Association + * A {@code MetaMessage} is a {@link MidiMessage} that is not meaningful to + * synthesizers, but that can be stored in a MIDI file and interpreted by a + * sequencer program. (See the discussion in the {@code MidiMessage} class + * description.) The Standard MIDI Files specification defines various types of + * meta-events, such as sequence number, lyric, cue point, and set tempo. There + * are also meta-events for such information as lyrics, copyrights, tempo + * indications, time and key signatures, markers, etc. For more information, see + * the Standard MIDI Files 1.0 specification, which is part of the Complete MIDI + * 1.0 Detailed Specification published by the MIDI Manufacturer's Association * (http://www.midi.org). - * *

    - * When data is being transported using MIDI wire protocol, - * a {@link ShortMessage} with the status value 0xFF represents - * a system reset message. In MIDI files, this same status value denotes a MetaMessage. - * The types of meta-message are distinguished from each other by the first byte - * that follows the status byte 0xFF. The subsequent bytes are data - * bytes. As with system exclusive messages, there are an arbitrary number of - * data bytes, depending on the type of MetaMessage. - * - * @see MetaEventListener + * When data is being transported using MIDI wire protocol, a + * {@link ShortMessage} with the status value {@code 0xFF} represents a system + * reset message. In MIDI files, this same status value denotes a + * {@code MetaMessage}. The types of meta-message are distinguished from each + * other by the first byte that follows the status byte {@code 0xFF}. The + * subsequent bytes are data bytes. As with system exclusive messages, there are + * an arbitrary number of data bytes, depending on the type of + * {@code MetaMessage}. * * @author David Rivas * @author Kara Kytle + * @see MetaEventListener */ - public class MetaMessage extends MidiMessage { - - // Status byte defines - /** - * Status byte for MetaMessage (0xFF, or 255), which is used - * in MIDI files. It has the same value as SYSTEM_RESET, which - * is used in the real-time "MIDI wire" protocol. + * Status byte for {@code MetaMessage} (0xFF, or 255), which is used in MIDI + * files. It has the same value as SYSTEM_RESET, which is used in the + * real-time "MIDI wire" protocol. + * * @see MidiMessage#getStatus */ public static final int META = 0xFF; // 255 - // Instance variables - /** - * The length of the actual message in the data array. - * This is used to determine how many bytes of the data array - * is the message, and how many are the status byte, the - * type byte, and the variable-length-int describing the - * length of the message. + * The length of the actual message in the data array. This is used to + * determine how many bytes of the data array is the message, and how many + * are the status byte, the type byte, and the variable-length-int + * describing the length of the message. */ private int dataLength = 0; - /** - * Constructs a new MetaMessage. The contents of - * the message are not set here; use - * {@link #setMessage(int, byte[], int) setMessage} - * to set them subsequently. + * Constructs a new {@code MetaMessage}. The contents of the message are not + * set here; use {@link #setMessage(int, byte[], int) setMessage} to set + * them subsequently. */ public MetaMessage() { // Default meta message data: just the META status byte value @@ -91,17 +80,17 @@ public class MetaMessage extends MidiMessage { } /** - * Constructs a new {@code MetaMessage} and sets the message parameters. - * The contents of the message can be changed by using - * the {@code setMessage} method. + * Constructs a new {@code MetaMessage} and sets the message parameters. The + * contents of the message can be changed by using the {@code setMessage} + * method. * - * @param type meta-message type (must be less than 128) - * @param data the data bytes in the MIDI message - * @param length an amount of bytes in the {@code data} byte array; - * it should be non-negative and less than or equal to - * {@code data.length} - * @throws InvalidMidiDataException if the parameter values do not specify - * a valid MIDI meta message + * @param type meta-message type (must be less than 128) + * @param data the data bytes in the MIDI message + * @param length an amount of bytes in the {@code data} byte array; it + * should be non-negative and less than or equal to + * {@code data.length} + * @throws InvalidMidiDataException if the parameter values do not specify a + * valid MIDI meta message * @see #setMessage(int, byte[], int) * @see #getType() * @see #getData() @@ -113,12 +102,11 @@ public class MetaMessage extends MidiMessage { setMessage(type, data, length); // can throw InvalidMidiDataException } - /** - * Constructs a new MetaMessage. - * @param data an array of bytes containing the complete message. - * The message data may be changed using the setMessage - * method. + * Constructs a new {@code MetaMessage}. + * + * @param data an array of bytes containing the complete message. The + * message data may be changed using the {@code setMessage} method. * @see #setMessage */ protected MetaMessage(byte[] data) { @@ -133,24 +121,24 @@ public class MetaMessage extends MidiMessage { } } - /** - * Sets the message parameters for a MetaMessage. - * Since only one status byte value, 0xFF, is allowed for meta-messages, - * it does not need to be specified here. Calls to {@link MidiMessage#getStatus getStatus} return - * 0xFF for all meta-messages. + * Sets the message parameters for a {@code MetaMessage}. Since only one + * status byte value, {@code 0xFF}, is allowed for meta-messages, it does + * not need to be specified here. Calls to + * {@link MidiMessage#getStatus getStatus} return {@code 0xFF} for all + * meta-messages. *

    - * The type argument should be a valid value for the byte that - * follows the status byte in the MetaMessage. The data argument - * should contain all the subsequent bytes of the MetaMessage. In other words, - * the byte that specifies the type of MetaMessage is not considered a data byte. + * The {@code type} argument should be a valid value for the byte that + * follows the status byte in the {@code MetaMessage}. The {@code data} + * argument should contain all the subsequent bytes of the + * {@code MetaMessage}. In other words, the byte that specifies the type of + * {@code MetaMessage} is not considered a data byte. * - * @param type meta-message type (must be less than 128) - * @param data the data bytes in the MIDI message - * @param length the number of bytes in the data - * byte array - * @throws InvalidMidiDataException if the - * parameter values do not specify a valid MIDI meta message + * @param type meta-message type (must be less than 128) + * @param data the data bytes in the MIDI message + * @param length the number of bytes in the {@code data} byte array + * @throws InvalidMidiDataException if the parameter values do not specify a + * valid MIDI meta message */ public void setMessage(int type, byte[] data, int length) throws InvalidMidiDataException { @@ -172,10 +160,10 @@ public class MetaMessage extends MidiMessage { } } - /** - * Obtains the type of the MetaMessage. - * @return an integer representing the MetaMessage type + * Obtains the type of the {@code MetaMessage}. + * + * @return an integer representing the {@code MetaMessage} type */ public int getType() { if (length>=2) { @@ -184,16 +172,15 @@ public class MetaMessage extends MidiMessage { return 0; } - - /** - * Obtains a copy of the data for the meta message. The returned - * array of bytes does not include the status byte or the message - * length data. The length of the data for the meta message is - * the length of the array. Note that the length of the entire - * message includes the status byte and the meta message type - * byte, and therefore may be longer than the returned array. - * @return array containing the meta message data. + * Obtains a copy of the data for the meta message. The returned array of + * bytes does not include the status byte or the message length data. The + * length of the data for the meta message is the length of the array. Note + * that the length of the entire message includes the status byte and the + * meta message type byte, and therefore may be longer than the returned + * array. + * + * @return array containing the meta message data * @see MidiMessage#getLength */ public byte[] getData() { @@ -202,10 +189,10 @@ public class MetaMessage extends MidiMessage { return returnedArray; } - /** - * Creates a new object of the same class and with the same contents - * as this object. + * Creates a new object of the same class and with the same contents as this + * object. + * * @return a clone of this instance */ public Object clone() { @@ -240,5 +227,4 @@ public class MetaMessage extends MidiMessage { } data[off] = (byte) (value & mask); } - } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiChannel.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiChannel.java index e2f37676304..6db7055ec83 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiChannel.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiChannel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,513 +25,450 @@ package javax.sound.midi; - /** - * A MidiChannel object represents a single MIDI channel. - * Generally, each MidiChannel method processes a like-named MIDI - * "channel voice" or "channel mode" message as defined by the MIDI specification. However, - * MidiChannel adds some "get" methods that retrieve the value - * most recently set by one of the standard MIDI channel messages. Similarly, - * methods for per-channel solo and mute have been added. + * A {@code MidiChannel} object represents a single MIDI channel. Generally, + * each {@code MidiChannel} method processes a like-named MIDI "channel voice" + * or "channel mode" message as defined by the MIDI specification. However, + * {@code MidiChannel} adds some "get" methods that retrieve the value most + * recently set by one of the standard MIDI channel messages. Similarly, methods + * for per-channel solo and mute have been added. *

    - * A {@link Synthesizer} object has a collection - * of MidiChannels, usually one for each of the 16 channels - * prescribed by the MIDI 1.0 specification. The Synthesizer - * generates sound when its MidiChannels receive - * noteOn messages. + * A {@link Synthesizer} object has a collection of {@code MidiChannels}, + * usually one for each of the 16 channels prescribed by the MIDI 1.0 + * specification. The {@code Synthesizer} generates sound when its + * {@code MidiChannels} receive {@code noteOn} messages. *

    * See the MIDI 1.0 Specification for more information about the prescribed - * behavior of the MIDI channel messages, which are not exhaustively - * documented here. The specification is titled MIDI Reference: - * The Complete MIDI 1.0 Detailed Specification, and is published by - * the MIDI Manufacturer's Association ( - * http://www.midi.org). + * behavior of the MIDI channel messages, which are not exhaustively documented + * here. The specification is titled + * {@code MIDI Reference: The Complete MIDI 1.0 Detailed Specification}, and is + * published by the MIDI Manufacturer's Association + * (http://www.midi.org). *

    * MIDI was originally a protocol for reporting the gestures of a keyboard - * musician. This genesis is visible in the MidiChannel API, which + * musician. This genesis is visible in the {@code MidiChannel} API, which * preserves such MIDI concepts as key number, key velocity, and key pressure. * It should be understood that the MIDI data does not necessarily originate * with a keyboard player (the source could be a different kind of musician, or - * software). Some devices might generate constant values for velocity - * and pressure, regardless of how the note was performed. - * Also, the MIDI specification often leaves it up to the - * synthesizer to use the data in the way the implementor sees fit. For - * example, velocity data need not always be mapped to volume and/or brightness. - * - * @see Synthesizer#getChannels + * software). Some devices might generate constant values for velocity and + * pressure, regardless of how the note was performed. Also, the MIDI + * specification often leaves it up to the synthesizer to use the data in the + * way the implementor sees fit. For example, velocity data need not always be + * mapped to volume and/or brightness. * * @author David Rivas * @author Kara Kytle + * @see Synthesizer#getChannels */ - public interface MidiChannel { /** - * Starts the specified note sounding. The key-down velocity - * usually controls the note's volume and/or brightness. - * If velocity is zero, this method instead acts like - * {@link #noteOff(int)}, terminating the note. - * - * @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C) - * @param velocity the speed with which the key was depressed + * Starts the specified note sounding. The key-down velocity usually + * controls the note's volume and/or brightness. If {@code velocity} is + * zero, this method instead acts like {@link #noteOff(int)}, terminating + * the note. * + * @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C) + * @param velocity the speed with which the key was depressed * @see #noteOff(int, int) */ - public void noteOn(int noteNumber, int velocity); + void noteOn(int noteNumber, int velocity); /** - * Turns the specified note off. The key-up velocity, if not ignored, can - * be used to affect how quickly the note decays. - * In any case, the note might not die away instantaneously; its decay - * rate is determined by the internals of the Instrument. - * If the Hold Pedal (a controller; see - * {@link #controlChange(int, int) controlChange}) - * is down, the effect of this method is deferred until the pedal is - * released. - * - * - * @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C) - * @param velocity the speed with which the key was released + * Turns the specified note off. The key-up velocity, if not ignored, can be + * used to affect how quickly the note decays. In any case, the note might + * not die away instantaneously; its decay rate is determined by the + * internals of the {@code Instrument}. If the Hold Pedal (a controller; see + * {@link #controlChange(int, int) controlChange}) is down, the effect of + * this method is deferred until the pedal is released. * + * @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C) + * @param velocity the speed with which the key was released * @see #noteOff(int) * @see #noteOn * @see #allNotesOff * @see #allSoundOff */ - public void noteOff(int noteNumber, int velocity); + void noteOff(int noteNumber, int velocity); /** * Turns the specified note off. * - * @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C) - * + * @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C) * @see #noteOff(int, int) */ - public void noteOff(int noteNumber); + void noteOff(int noteNumber); /** - * Reacts to a change in the specified note's key pressure. - * Polyphonic key pressure - * allows a keyboard player to press multiple keys simultaneously, each - * with a different amount of pressure. The pressure, if not ignored, - * is typically used to vary such features as the volume, brightness, - * or vibrato of the note. - * - * It is possible that the underlying synthesizer - * does not support this MIDI message. In order - * to verify that setPolyPressure - * was successful, use getPolyPressure. - * - * @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C) - * @param pressure value for the specified key, from 0 to 127 (127 = - * maximum pressure) + * Reacts to a change in the specified note's key pressure. Polyphonic key + * pressure allows a keyboard player to press multiple keys simultaneously, + * each with a different amount of pressure. The pressure, if not ignored, + * is typically used to vary such features as the volume, brightness, or + * vibrato of the note. + *

    + * It is possible that the underlying synthesizer does not support this MIDI + * message. In order to verify that {@code setPolyPressure} was successful, + * use {@code getPolyPressure}. * + * @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C) + * @param pressure value for the specified key, from 0 to 127 + * (127 = maximum pressure) * @see #getPolyPressure(int) */ - public void setPolyPressure(int noteNumber, int pressure); + void setPolyPressure(int noteNumber, int pressure); /** * Obtains the pressure with which the specified key is being depressed. + *

    + * If the device does not support setting poly pressure, this method always + * returns 0. Calling {@code setPolyPressure} will have no effect then. * - * @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C) - * - * If the device does not support setting poly pressure, - * this method always returns 0. Calling - * setPolyPressure will have no effect then. - * + * @param noteNumber the MIDI note number, from 0 to 127 (60 = Middle C) * @return the amount of pressure for that note, from 0 to 127 - * (127 = maximum pressure) - * + * (127 = maximum pressure) * @see #setPolyPressure(int, int) */ - public int getPolyPressure(int noteNumber); + int getPolyPressure(int noteNumber); /** - * Reacts to a change in the keyboard pressure. Channel - * pressure indicates how hard the keyboard player is depressing - * the entire keyboard. This can be the maximum or - * average of the per-key pressure-sensor values, as set by - * setPolyPressure. More commonly, it is a measurement of - * a single sensor on a device that doesn't implement polyphonic key - * pressure. Pressure can be used to control various aspects of the sound, - * as described under {@link #setPolyPressure(int, int) setPolyPressure}. + * Reacts to a change in the keyboard pressure. Channel pressure indicates + * how hard the keyboard player is depressing the entire keyboard. This can + * be the maximum or average of the per-key pressure-sensor values, as set + * by {@code setPolyPressure}. More commonly, it is a measurement of a + * single sensor on a device that doesn't implement polyphonic key pressure. + * Pressure can be used to control various aspects of the sound, as + * described under {@link #setPolyPressure(int, int) setPolyPressure}. + *

    + * It is possible that the underlying synthesizer does not support this MIDI + * message. In order to verify that {@code setChannelPressure} was + * successful, use {@code getChannelPressure}. * - * It is possible that the underlying synthesizer - * does not support this MIDI message. In order - * to verify that setChannelPressure - * was successful, use getChannelPressure. - * - * @param pressure the pressure with which the keyboard is being depressed, - * from 0 to 127 (127 = maximum pressure) + * @param pressure the pressure with which the keyboard is being depressed, + * from 0 to 127 (127 = maximum pressure) * @see #setPolyPressure(int, int) * @see #getChannelPressure */ - public void setChannelPressure(int pressure); + void setChannelPressure(int pressure); /** * Obtains the channel's keyboard pressure. - * If the device does not support setting channel pressure, - * this method always returns 0. Calling - * setChannelPressure will have no effect then. - * - * @return the amount of pressure for that note, - * from 0 to 127 (127 = maximum pressure) + *

    + * If the device does not support setting channel pressure, this method + * always returns 0. Calling {@code setChannelPressure} will have no effect + * then. * + * @return the amount of pressure for that note, from 0 to 127 + * (127 = maximum pressure) * @see #setChannelPressure(int) */ - public int getChannelPressure(); + int getChannelPressure(); /** - * Reacts to a change in the specified controller's value. A controller - * is some control other than a keyboard key, such as a - * switch, slider, pedal, wheel, or breath-pressure sensor. - * The MIDI 1.0 Specification provides standard numbers for typical - * controllers on MIDI devices, and describes the intended effect - * for some of the controllers. - * The way in which an - * Instrument reacts to a controller change may be - * specific to the Instrument. + * Reacts to a change in the specified controller's value. A controller is + * some control other than a keyboard key, such as a switch, slider, pedal, + * wheel, or breath-pressure sensor. The MIDI 1.0 Specification provides + * standard numbers for typical controllers on MIDI devices, and describes + * the intended effect for some of the controllers. The way in which an + * {@code Instrument} reacts to a controller change may be specific to the + * {@code Instrument}. *

    - * The MIDI 1.0 Specification defines both 7-bit controllers - * and 14-bit controllers. Continuous controllers, such - * as wheels and sliders, typically have 14 bits (two MIDI bytes), - * while discrete controllers, such as switches, typically have 7 bits - * (one MIDI byte). Refer to the specification to see the - * expected resolution for each type of control. + * The MIDI 1.0 Specification defines both 7-bit controllers and 14-bit + * controllers. Continuous controllers, such as wheels and sliders, + * typically have 14 bits (two MIDI bytes), while discrete controllers, such + * as switches, typically have 7 bits (one MIDI byte). Refer to the + * specification to see the expected resolution for each type of control. *

    - * Controllers 64 through 95 (0x40 - 0x5F) allow 7-bit precision. - * The value of a 7-bit controller is set completely by the - * value argument. An additional set of controllers - * provide 14-bit precision by using two controller numbers, one - * for the most significant 7 bits and another for the least significant - * 7 bits. Controller numbers 0 through 31 (0x00 - 0x1F) control the - * most significant 7 bits of 14-bit controllers; controller numbers - * 32 through 63 (0x20 - 0x3F) control the least significant 7 bits of - * these controllers. For example, controller number 7 (0x07) controls - * the upper 7 bits of the channel volume controller, and controller - * number 39 (0x27) controls the lower 7 bits. - * The value of a 14-bit controller is determined - * by the interaction of the two halves. When the most significant 7 bits - * of a controller are set (using controller numbers 0 through 31), the - * lower 7 bits are automatically set to 0. The corresponding controller - * number for the lower 7 bits may then be used to further modulate the - * controller value. - * - * It is possible that the underlying synthesizer - * does not support a specific controller message. In order - * to verify that a call to controlChange - * was successful, use getController. - * - * @param controller the controller number (0 to 127; see the MIDI - * 1.0 Specification for the interpretation) - * @param value the value to which the specified controller is changed (0 to 127) + * Controllers 64 through 95 (0x40 - 0x5F) allow 7-bit precision. The value + * of a 7-bit controller is set completely by the {@code value} argument. An + * additional set of controllers provide 14-bit precision by using two + * controller numbers, one for the most significant 7 bits and another for + * the least significant 7 bits. Controller numbers 0 through 31 + * (0x00 - 0x1F) control the most significant 7 bits of 14-bit controllers; + * controller numbers 32 through 63 (0x20 - 0x3F) control the least + * significant 7 bits of these controllers. For example, controller number 7 + * (0x07) controls the upper 7 bits of the channel volume controller, and + * controller number 39 (0x27) controls the lower 7 bits. The value of a + * 14-bit controller is determined by the interaction of the two halves. + * When the most significant 7 bits of a controller are set (using + * controller numbers 0 through 31), the lower 7 bits are automatically set + * to 0. The corresponding controller number for the lower 7 bits may then + * be used to further modulate the controller value. + *

    + * It is possible that the underlying synthesizer does not support a + * specific controller message. In order to verify that a call to + * {@code controlChange} was successful, use {@code getController}. * + * @param controller the controller number (0 to 127; see the MIDI 1.0 + * Specification for the interpretation) + * @param value the value to which the specified controller is changed + * (0 to 127) * @see #getController(int) */ - public void controlChange(int controller, int value); + void controlChange(int controller, int value); /** - * Obtains the current value of the specified controller. The return - * value is represented with 7 bits. For 14-bit controllers, the MSB and - * LSB controller value needs to be obtained separately. For example, - * the 14-bit value of the volume controller can be calculated by - * multiplying the value of controller 7 (0x07, channel volume MSB) - * with 128 and adding the - * value of controller 39 (0x27, channel volume LSB). - * - * If the device does not support setting a specific controller, - * this method returns 0 for that controller. - * Calling controlChange will have no effect then. - * - * @param controller the number of the controller whose value is desired. - * The allowed range is 0-127; see the MIDI - * 1.0 Specification for the interpretation. + * Obtains the current value of the specified controller. The return value + * is represented with 7 bits. For 14-bit controllers, the MSB and LSB + * controller value needs to be obtained separately. For example, the 14-bit + * value of the volume controller can be calculated by multiplying the value + * of controller 7 (0x07, channel volume MSB) with 128 and adding the value + * of controller 39 (0x27, channel volume LSB). + *

    + * If the device does not support setting a specific controller, this method + * returns 0 for that controller. Calling {@code controlChange} will have no + * effect then. * + * @param controller the number of the controller whose value is desired. + * The allowed range is 0-127; see the MIDI 1.0 Specification for + * the interpretation. * @return the current value of the specified controller (0 to 127) - * * @see #controlChange(int, int) */ - public int getController(int controller); + int getController(int controller); /** - * Changes a program (patch). This selects a specific - * instrument from the currently selected bank of instruments. + * Changes a program (patch). This selects a specific instrument from the + * currently selected bank of instruments. *

    - * The MIDI specification does not - * dictate whether notes that are already sounding should switch - * to the new instrument (timbre) or continue with their original timbre - * until terminated by a note-off. + * The MIDI specification does not dictate whether notes that are already + * sounding should switch to the new instrument (timbre) or continue with + * their original timbre until terminated by a note-off. *

    - * The program number is zero-based (expressed from 0 to 127). - * Note that MIDI hardware displays and literature about MIDI - * typically use the range 1 to 128 instead. - * - * It is possible that the underlying synthesizer - * does not support a specific program. In order - * to verify that a call to programChange - * was successful, use getProgram. - * - * @param program the program number to switch to (0 to 127) + * The program number is zero-based (expressed from 0 to 127). Note that + * MIDI hardware displays and literature about MIDI typically use the range + * 1 to 128 instead. + *

    + * It is possible that the underlying synthesizer does not support a + * specific program. In order to verify that a call to {@code programChange} + * was successful, use {@code getProgram}. * + * @param program the program number to switch to (0 to 127) * @see #programChange(int, int) * @see #getProgram() */ - public void programChange(int program); + void programChange(int program); /** * Changes the program using bank and program (patch) numbers. - * - * It is possible that the underlying synthesizer - * does not support a specific bank, or program. In order - * to verify that a call to programChange - * was successful, use getProgram and - * getController. - * Since banks are changed by way of control changes, - * you can verify the current bank with the following - * statement: + *

    + * It is possible that the underlying synthesizer does not support a + * specific bank, or program. In order to verify that a call to + * {@code programChange} was successful, use {@code getProgram} and + * {@code getController}. Since banks are changed by way of control changes, + * you can verify the current bank with the following statement: *

    -     *   int bank = (getController(0) * 128)
    -     *              + getController(32);
    +     *   int bank = (getController(0) * 128) + getController(32);
          * 
    * - * @param bank the bank number to switch to (0 to 16383) - * @param program the program (patch) to use in the specified bank (0 to 127) + * @param bank the bank number to switch to (0 to 16383) + * @param program the program (patch) to use in the specified bank + * (0 to 127) * @see #programChange(int) * @see #getProgram() */ - public void programChange(int bank, int program); + void programChange(int bank, int program); /** * Obtains the current program number for this channel. + * * @return the program number of the currently selected patch * @see Patch#getProgram * @see Synthesizer#loadInstrument * @see #programChange(int) */ - public int getProgram(); + int getProgram(); /** - * Changes the pitch offset for all notes on this channel. - * This affects all currently sounding notes as well as subsequent ones. - * (For pitch bend to cease, the value needs to be reset to the - * center position.) - *

    The MIDI specification - * stipulates that pitch bend be a 14-bit value, where zero - * is maximum downward bend, 16383 is maximum upward bend, and - * 8192 is the center (no pitch bend). The actual - * amount of pitch change is not specified; it can be changed by - * a pitch-bend sensitivity setting. However, the General MIDI - * specification says that the default range should be two semitones - * up and down from center. - * - * It is possible that the underlying synthesizer - * does not support this MIDI message. In order - * to verify that setPitchBend - * was successful, use getPitchBend. - * - * @param bend the amount of pitch change, as a nonnegative 14-bit value - * (8192 = no bend) + * Changes the pitch offset for all notes on this channel. This affects all + * currently sounding notes as well as subsequent ones. (For pitch bend to + * cease, the value needs to be reset to the center position.) + *

    + * The MIDI specification stipulates that pitch bend be a 14-bit value, + * where zero is maximum downward bend, 16383 is maximum upward bend, and + * 8192 is the center (no pitch bend). The actual amount of pitch change is + * not specified; it can be changed by a pitch-bend sensitivity setting. + * However, the General MIDI specification says that the default range + * should be two semitones up and down from center. + *

    + * It is possible that the underlying synthesizer does not support this MIDI + * message. In order to verify that {@code setPitchBend} was successful, use + * {@code getPitchBend}. * + * @param bend the amount of pitch change, as a nonnegative 14-bit value + * (8192 = no bend) * @see #getPitchBend */ - public void setPitchBend(int bend); + void setPitchBend(int bend); /** - * Obtains the upward or downward pitch offset for this channel. - * If the device does not support setting pitch bend, - * this method always returns 8192. Calling - * setPitchBend will have no effect then. + * Obtains the upward or downward pitch offset for this channel. If the + * device does not support setting pitch bend, this method always returns + * 8192. Calling {@code setPitchBend} will have no effect then. * * @return bend amount, as a nonnegative 14-bit value (8192 = no bend) - * * @see #setPitchBend(int) */ - public int getPitchBend(); + int getPitchBend(); /** * Resets all the implemented controllers to their default values. * * @see #controlChange(int, int) */ - public void resetAllControllers(); + void resetAllControllers(); /** - * Turns off all notes that are currently sounding on this channel. - * The notes might not die away instantaneously; their decay - * rate is determined by the internals of the Instrument. - * If the Hold Pedal controller (see - * {@link #controlChange(int, int) controlChange}) - * is down, the effect of this method is deferred until the pedal is - * released. + * Turns off all notes that are currently sounding on this channel. The + * notes might not die away instantaneously; their decay rate is determined + * by the internals of the {@code Instrument}. If the Hold Pedal controller + * (see {@link #controlChange(int, int) controlChange}) is down, the effect + * of this method is deferred until the pedal is released. * * @see #allSoundOff * @see #noteOff(int) */ - public void allNotesOff(); + void allNotesOff(); /** * Immediately turns off all sounding notes on this channel, ignoring the * state of the Hold Pedal and the internal decay rate of the current - * Instrument. + * {@code Instrument}. * * @see #allNotesOff */ - public void allSoundOff(); + void allSoundOff(); /** - * Turns local control on or off. The default is for local control - * to be on. The "on" setting means that if a device is capable - * of both synthesizing sound and transmitting MIDI messages, - * it will synthesize sound in response to the note-on and - * note-off messages that it itself transmits. It will also respond - * to messages received from other transmitting devices. - * The "off" setting means that the synthesizer will ignore its - * own transmitted MIDI messages, but not those received from other devices. - * - * It is possible that the underlying synthesizer - * does not support local control. In order - * to verify that a call to localControl - * was successful, check the return value. - * - * @param on true to turn local control on, false - * to turn local control off - * @return the new local-control value, or false - * if local control is not supported - * - */ - public boolean localControl(boolean on); - - /** - * Turns mono mode on or off. In mono mode, the channel synthesizes - * only one note at a time. In poly mode (identical to mono mode off), - * the channel can synthesize multiple notes simultaneously. - * The default is mono off (poly mode on). + * Turns local control on or off. The default is for local control to be on. + * The "on" setting means that if a device is capable of both synthesizing + * sound and transmitting MIDI messages, it will synthesize sound in + * response to the note-on and note-off messages that it itself transmits. + * It will also respond to messages received from other transmitting + * devices. The "off" setting means that the synthesizer will ignore its own + * transmitted MIDI messages, but not those received from other devices. *

    - * "Mono" is short for the word "monophonic," which in this context - * is opposed to the word "polyphonic" and refers to a single synthesizer - * voice per MIDI channel. It - * has nothing to do with how many audio channels there might be - * (as in "monophonic" versus "stereophonic" recordings). + * It is possible that the underlying synthesizer does not support local + * control. In order to verify that a call to {@code localControl} was + * successful, check the return value. * - * It is possible that the underlying synthesizer - * does not support mono mode. In order - * to verify that a call to setMono - * was successful, use getMono. - * - * @param on true to turn mono mode on, false to - * turn it off (which means turning poly mode on). + * @param on {@code true} to turn local control on, {@code false} to turn + * local control off + * @return the new local-control value, or false if local control is not + * supported + */ + boolean localControl(boolean on); + + /** + * Turns mono mode on or off. In mono mode, the channel synthesizes only one + * note at a time. In poly mode (identical to mono mode off), the channel + * can synthesize multiple notes simultaneously. The default is mono off + * (poly mode on). + *

    + * "Mono" is short for the word "monophonic," which in this context is + * opposed to the word "polyphonic" and refers to a single synthesizer voice + * per MIDI channel. It has nothing to do with how many audio channels there + * might be (as in "monophonic" versus "stereophonic" recordings). + *

    + * It is possible that the underlying synthesizer does not support mono + * mode. In order to verify that a call to {@code setMono} was successful, + * use {@code getMono}. * + * @param on {@code true} to turn mono mode on, {@code false} to turn it + * off (which means turning poly mode on) * @see #getMono * @see VoiceStatus */ - public void setMono(boolean on); + void setMono(boolean on); /** - * Obtains the current mono/poly mode. - * Synthesizers that do not allow changing mono/poly mode - * will always return the same value, regardless - * of calls to setMono. - * @return true if mono mode is on, otherwise - * false (meaning poly mode is on). + * Obtains the current mono/poly mode. Synthesizers that do not allow + * changing mono/poly mode will always return the same value, regardless of + * calls to {@code setMono}. * + * @return {@code true} if mono mode is on, otherwise {@code false} (meaning + * poly mode is on) * @see #setMono(boolean) */ - public boolean getMono(); + boolean getMono(); /** - * Turns omni mode on or off. In omni mode, the channel responds - * to messages sent on all channels. When omni is off, the channel - * responds only to messages sent on its channel number. - * The default is omni off. - * - * It is possible that the underlying synthesizer - * does not support omni mode. In order - * to verify that setOmni - * was successful, use getOmni. - * - * @param on true to turn omni mode on, false to - * turn it off. + * Turns omni mode on or off. In omni mode, the channel responds to messages + * sent on all channels. When omni is off, the channel responds only to + * messages sent on its channel number. The default is omni off. + *

    + * It is possible that the underlying synthesizer does not support omni + * mode. In order to verify that {@code setOmni} was successful, use + * {@code getOmni}. * + * @param on {@code true} to turn omni mode on, {@code false} to turn it + * off * @see #getOmni * @see VoiceStatus */ - public void setOmni(boolean on); + void setOmni(boolean on); /** - * Obtains the current omni mode. - * Synthesizers that do not allow changing the omni mode - * will always return the same value, regardless - * of calls to setOmni. - * @return true if omni mode is on, otherwise - * false (meaning omni mode is off). + * Obtains the current omni mode. Synthesizers that do not allow changing + * the omni mode will always return the same value, regardless of calls to + * {@code setOmni}. * + * @return {@code true} if omni mode is on, otherwise {@code false} (meaning + * omni mode is off) * @see #setOmni(boolean) */ - public boolean getOmni(); + boolean getOmni(); /** - * Sets the mute state for this channel. A value of - * true means the channel is to be muted, false - * means the channel can sound (if other channels are not soloed). + * Sets the mute state for this channel. A value of {@code true} means the + * channel is to be muted, {@code false} means the channel can sound (if + * other channels are not soloed). *

    - * Unlike {@link #allSoundOff()}, this method - * applies to only a specific channel, not to all channels. Further, it - * silences not only currently sounding notes, but also subsequently - * received notes. - * - * It is possible that the underlying synthesizer - * does not support muting channels. In order - * to verify that a call to setMute - * was successful, use getMute. - * - * @param mute the new mute state + * Unlike {@link #allSoundOff()}, this method applies to only a specific + * channel, not to all channels. Further, it silences not only currently + * sounding notes, but also subsequently received notes. + *

    + * It is possible that the underlying synthesizer does not support muting + * channels. In order to verify that a call to {@code setMute} was + * successful, use {@code getMute}. * + * @param mute the new mute state * @see #getMute * @see #setSolo(boolean) */ - public void setMute(boolean mute); + void setMute(boolean mute); /** - * Obtains the current mute state for this channel. - * If the underlying synthesizer does not support - * muting this channel, this method always returns - * false. - * - * @return true the channel is muted, - * or false if not + * Obtains the current mute state for this channel. If the underlying + * synthesizer does not support muting this channel, this method always + * returns {@code false}. * + * @return {@code true} the channel is muted, or {@code false} if not * @see #setMute(boolean) */ - public boolean getMute(); + boolean getMute(); /** - * Sets the solo state for this channel. - * If solo is true only this channel - * and other soloed channels will sound. If solo - * is false then only other soloed channels will - * sound, unless no channels are soloed, in which case all - * unmuted channels will sound. + * Sets the solo state for this channel. If {@code solo} is {@code true} + * only this channel and other soloed channels will sound. If {@code solo} + * is {@code false} then only other soloed channels will sound, unless no + * channels are soloed, in which case all unmuted channels will sound. + *

    + * It is possible that the underlying synthesizer does not support solo + * channels. In order to verify that a call to {@code setSolo} was + * successful, use {@code getSolo}. * - * It is possible that the underlying synthesizer - * does not support solo channels. In order - * to verify that a call to setSolo - * was successful, use getSolo. - * - * @param soloState new solo state for the channel + * @param soloState new solo state for the channel * @see #getSolo() */ - public void setSolo(boolean soloState); + void setSolo(boolean soloState); /** - * Obtains the current solo state for this channel. - * If the underlying synthesizer does not support - * solo on this channel, this method always returns - * false. - * - * @return true the channel is solo, - * or false if not + * Obtains the current solo state for this channel. If the underlying + * synthesizer does not support solo on this channel, this method always + * returns {@code false}. * + * @return {@code true} the channel is solo, or {@code false} if not * @see #setSolo(boolean) */ - public boolean getSolo(); + boolean getSolo(); } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDevice.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDevice.java index f53d4ff3e2f..43c82932f6a 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDevice.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDevice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -27,64 +27,52 @@ package javax.sound.midi; import java.util.List; - /** - * MidiDevice is the base interface for all MIDI devices. - * Common devices include synthesizers, sequencers, MIDI input ports, and MIDI - * output ports. - * - *

    A MidiDevice can be a transmitter or a receiver of - * MIDI events, or both. Therefore, it can provide {@link Transmitter} - * or {@link Receiver} instances (or both). Typically, MIDI IN ports - * provide transmitters, MIDI OUT ports and synthesizers provide - * receivers. A Sequencer typically provides transmitters for playback - * and receivers for recording. - * - *

    A MidiDevice can be opened and closed explicitly as - * well as implicitly. Explicit opening is accomplished by calling - * {@link #open}, explicit closing is done by calling {@link - * #close} on the MidiDevice instance. - * If an application opens a MidiDevice - * explicitly, it has to close it explicitly to free system resources - * and enable the application to exit cleanly. Implicit opening is - * done by calling {@link javax.sound.midi.MidiSystem#getReceiver - * MidiSystem.getReceiver} and {@link - * javax.sound.midi.MidiSystem#getTransmitter - * MidiSystem.getTransmitter}. The MidiDevice used by - * MidiSystem.getReceiver and - * MidiSystem.getTransmitter is implementation-dependant - * unless the properties javax.sound.midi.Receiver - * and javax.sound.midi.Transmitter are used (see the - * description of properties to select default providers in - * {@link javax.sound.midi.MidiSystem}). A MidiDevice - * that was opened implicitly, is closed implicitly by closing the - * Receiver or Transmitter that resulted in - * opening it. If more than one implicitly opening - * Receiver or Transmitter were obtained by - * the application, the device is closed after the last - * Receiver or Transmitter has been - * closed. On the other hand, calling getReceiver or - * getTransmitter on the device instance directly does - * not open the device implicitly. Closing these - * Transmitters and Receivers does not close - * the device implicitly. To use a device with Receivers - * or Transmitters obtained this way, the device has to - * be opened and closed explicitly. - * - *

    If implicit and explicit opening and closing are mixed on the - * same MidiDevice instance, the following rules apply: +/** + * {@code MidiDevice} is the base interface for all MIDI devices. Common devices + * include synthesizers, sequencers, MIDI input ports, and MIDI output ports. + *

    + * A {@code MidiDevice} can be a transmitter or a receiver of MIDI events, or + * both. Therefore, it can provide {@link Transmitter} or {@link Receiver} + * instances (or both). Typically, MIDI IN ports provide transmitters, MIDI OUT + * ports and synthesizers provide receivers. A Sequencer typically provides + * transmitters for playback and receivers for recording. + *

    + * A {@code MidiDevice} can be opened and closed explicitly as well as + * implicitly. Explicit opening is accomplished by calling {@link #open}, + * explicit closing is done by calling {@link #close} on the {@code MidiDevice} + * instance. If an application opens a {@code MidiDevice} explicitly, it has to + * close it explicitly to free system resources and enable the application to + * exit cleanly. Implicit opening is done by calling + * {@link MidiSystem#getReceiver} and {@link MidiSystem#getTransmitter}. The + * {@code MidiDevice} used by {@code MidiSystem.getReceiver} and + * {@code MidiSystem.getTransmitter} is implementation-dependant unless the + * properties {@code javax.sound.midi.Receiver} and + * {@code javax.sound.midi.Transmitter} are used (see the description of + * properties to select default providers in {@link MidiSystem}). A + * {@code MidiDevice} that was opened implicitly, is closed implicitly by + * closing the {@code Receiver} or {@code Transmitter} that resulted in opening + * it. If more than one implicitly opening {@code Receiver} or + * {@code Transmitter} were obtained by the application, the device is closed + * after the last {@code Receiver} or {@code Transmitter} has been closed. On + * the other hand, calling {@code getReceiver} or {@code getTransmitter} on the + * device instance directly does not open the device implicitly. Closing these + * {@code Transmitter}s and {@code Receiver}s does not close the device + * implicitly. To use a device with {@code Receiver}s or {@code Transmitter}s + * obtained this way, the device has to be opened and closed explicitly. + *

    + * If implicit and explicit opening and closing are mixed on the same + * {@code MidiDevice} instance, the following rules apply: * *

      - *
    • After an explicit open (either before or after implicit - * opens), the device will not be closed by implicit closing. The only - * way to close an explicitly opened device is an explicit close.
    • - * - *
    • An explicit close always closes the device, even if it also has - * been opened implicitly. A subsequent implicit close has no further - * effect.
    • + *
    • After an explicit open (either before or after implicit opens), the + * device will not be closed by implicit closing. The only way to close an + * explicitly opened device is an explicit close.
    • + *
    • An explicit close always closes the device, even if it also has been + * opened implicitly. A subsequent implicit close has no further effect.
    • *
    * - * To detect if a MidiDevice represents a hardware MIDI port, the - * following programming technique can be used: + * To detect if a MidiDevice represents a hardware MIDI port, the following + * programming technique can be used: * *
    {@code
      * MidiDevice device = ...;
    @@ -95,193 +83,171 @@ import java.util.List;
      * }
    * *

    - * A MidiDevice includes a {@link MidiDevice.Info} object - * to provide manufacturer information and so on. + * A {@code MidiDevice} includes a {@link Info} object to provide manufacturer + * information and so on. * + * @author Kara Kytle + * @author Florian Bomers * @see Synthesizer * @see Sequencer * @see Receiver * @see Transmitter - * - * @author Kara Kytle - * @author Florian Bomers */ - public interface MidiDevice extends AutoCloseable { - /** * Obtains information about the device, including its Java class and - * Strings containing its name, vendor, and description. + * {@code Strings} containing its name, vendor, and description. * * @return device info */ - public Info getDeviceInfo(); - + Info getDeviceInfo(); /** - * Opens the device, indicating that it should now acquire any - * system resources it requires and become operational. - * - *

    An application opening a device explicitly with this call - * has to close the device by calling {@link #close}. This is - * necessary to release system resources and allow applications to - * exit cleanly. - * + * Opens the device, indicating that it should now acquire any system + * resources it requires and become operational. *

    - * Note that some devices, once closed, cannot be reopened. Attempts - * to reopen such a device will always result in a MidiUnavailableException. - * - * @throws MidiUnavailableException thrown if the device cannot be - * opened due to resource restrictions. - * @throws SecurityException thrown if the device cannot be - * opened due to security restrictions. + * An application opening a device explicitly with this call has to close + * the device by calling {@link #close}. This is necessary to release system + * resources and allow applications to exit cleanly. + *

    + * Note that some devices, once closed, cannot be reopened. Attempts to + * reopen such a device will always result in a MidiUnavailableException. * + * @throws MidiUnavailableException thrown if the device cannot be opened + * due to resource restrictions + * @throws SecurityException thrown if the device cannot be opened due to + * security restrictions * @see #close * @see #isOpen */ - public void open() throws MidiUnavailableException; - + void open() throws MidiUnavailableException; /** - * Closes the device, indicating that the device should now release - * any system resources it is using. - * - *

    All Receiver and Transmitter instances - * open from this device are closed. This includes instances retrieved - * via MidiSystem. + * Closes the device, indicating that the device should now release any + * system resources it is using. + *

    + * All {@code Receiver} and {@code Transmitter} instances open from this + * device are closed. This includes instances retrieved via + * {@code MidiSystem}. * * @see #open * @see #isOpen */ - public void close(); - + void close(); /** * Reports whether the device is open. * - * @return true if the device is open, otherwise - * false + * @return {@code true} if the device is open, otherwise {@code false} * @see #open * @see #close */ - public boolean isOpen(); - + boolean isOpen(); /** - * Obtains the current time-stamp of the device, in microseconds. - * If a device supports time-stamps, it should start counting at - * 0 when the device is opened and continue incrementing its - * time-stamp in microseconds until the device is closed. - * If it does not support time-stamps, it should always return - * -1. - * @return the current time-stamp of the device in microseconds, - * or -1 if time-stamping is not supported by the device. - */ - public long getMicrosecondPosition(); - - - /** - * Obtains the maximum number of MIDI IN connections available on this - * MIDI device for receiving MIDI data. - * @return maximum number of MIDI IN connections, - * or -1 if an unlimited number of connections is available. - */ - public int getMaxReceivers(); - - - /** - * Obtains the maximum number of MIDI OUT connections available on this - * MIDI device for transmitting MIDI data. - * @return maximum number of MIDI OUT connections, - * or -1 if an unlimited number of connections is available. - */ - public int getMaxTransmitters(); - - - /** - * Obtains a MIDI IN receiver through which the MIDI device may receive - * MIDI data. The returned receiver must be closed when the application - * has finished using it. + * Obtains the current time-stamp of the device, in microseconds. If a + * device supports time-stamps, it should start counting at 0 when the + * device is opened and continue incrementing its time-stamp in microseconds + * until the device is closed. If it does not support time-stamps, it should + * always return -1. * - *

    Usually the returned receiver implements - * the {@code MidiDeviceReceiver} interface. + * @return the current time-stamp of the device in microseconds, or -1 if + * time-stamping is not supported by the device + */ + long getMicrosecondPosition(); + + /** + * Obtains the maximum number of MIDI IN connections available on this MIDI + * device for receiving MIDI data. * - *

    Obtaining a Receiver with this method does not - * open the device. To be able to use the device, it has to be - * opened explicitly by calling {@link #open}. Also, closing the - * Receiver does not close the device. It has to be - * closed explicitly by calling {@link #close}. + * @return maximum number of MIDI IN connections, or -1 if an unlimited + * number of connections is available + */ + int getMaxReceivers(); + + /** + * Obtains the maximum number of MIDI OUT connections available on this MIDI + * device for transmitting MIDI data. * - * @return a receiver for the device. + * @return maximum number of MIDI OUT connections, or -1 if an unlimited + * number of connections is available + */ + int getMaxTransmitters(); + + /** + * Obtains a MIDI IN receiver through which the MIDI device may receive MIDI + * data. The returned receiver must be closed when the application has + * finished using it. + *

    + * Usually the returned receiver implements the {@code MidiDeviceReceiver} + * interface. + *

    + * Obtaining a {@code Receiver} with this method does not open the device. + * To be able to use the device, it has to be opened explicitly by calling + * {@link #open}. Also, closing the {@code Receiver} does not close the + * device. It has to be closed explicitly by calling {@link #close}. + * + * @return a receiver for the device * @throws MidiUnavailableException thrown if a receiver is not available - * due to resource restrictions + * due to resource restrictions * @see Receiver#close() */ - public Receiver getReceiver() throws MidiUnavailableException; - + Receiver getReceiver() throws MidiUnavailableException; /** - * Returns all currently active, non-closed receivers - * connected with this MidiDevice. - * A receiver can be removed - * from the device by closing it. - * - *

    Usually the returned receivers implement - * the {@code MidiDeviceReceiver} interface. + * Returns all currently active, non-closed receivers connected with this + * MidiDevice. A receiver can be removed from the device by closing it. + *

    + * Usually the returned receivers implement the {@code MidiDeviceReceiver} + * interface. * * @return an unmodifiable list of the open receivers * @since 1.5 */ List getReceivers(); - /** * Obtains a MIDI OUT connection from which the MIDI device will transmit - * MIDI data The returned transmitter must be closed when the application + * MIDI data. The returned transmitter must be closed when the application * has finished using it. + *

    + * Usually the returned transmitter implements the + * {@code MidiDeviceTransmitter} interface. + *

    + * Obtaining a {@code Transmitter} with this method does not open the + * device. To be able to use the device, it has to be opened explicitly by + * calling {@link #open}. Also, closing the {@code Transmitter} does not + * close the device. It has to be closed explicitly by calling + * {@link #close}. * - *

    Usually the returned transmitter implements - * the {@code MidiDeviceTransmitter} interface. - * - *

    Obtaining a Transmitter with this method does not - * open the device. To be able to use the device, it has to be - * opened explicitly by calling {@link #open}. Also, closing the - * Transmitter does not close the device. It has to be - * closed explicitly by calling {@link #close}. - * - * @return a MIDI OUT transmitter for the device. + * @return a MIDI OUT transmitter for the device * @throws MidiUnavailableException thrown if a transmitter is not available - * due to resource restrictions + * due to resource restrictions * @see Transmitter#close() */ - public Transmitter getTransmitter() throws MidiUnavailableException; - + Transmitter getTransmitter() throws MidiUnavailableException; /** - * Returns all currently active, non-closed transmitters - * connected with this MidiDevice. - * A transmitter can be removed - * from the device by closing it. - * - *

    Usually the returned transmitters implement - * the {@code MidiDeviceTransmitter} interface. + * Returns all currently active, non-closed transmitters connected with this + * MidiDevice. A transmitter can be removed from the device by closing it. + *

    + * Usually the returned transmitters implement the + * {@code MidiDeviceTransmitter} interface. * * @return an unmodifiable list of the open transmitters * @since 1.5 */ List getTransmitters(); - - /** - * A MidiDevice.Info object contains assorted - * data about a {@link MidiDevice}, including its - * name, the company who created it, and descriptive text. + * A {@code MidiDevice.Info} object contains assorted data about a + * {@link MidiDevice}, including its name, the company who created it, and + * descriptive text. * * @see MidiDevice#getDeviceInfo */ - public static class Info { + class Info { /** * The device's name. @@ -303,16 +269,16 @@ public interface MidiDevice extends AutoCloseable { */ private String version; - /** * Constructs a device info object. * - * @param name the name of the device - * @param vendor the name of the company who provides the device - * @param description a description of the device - * @param version version information for the device + * @param name the name of the device + * @param vendor the name of the company who provides the device + * @param description a description of the device + * @param version version information for the device */ - protected Info(String name, String vendor, String description, String version) { + protected Info(String name, String vendor, String description, + String version) { this.name = name; this.vendor = vendor; @@ -320,20 +286,18 @@ public interface MidiDevice extends AutoCloseable { this.version = version; } - /** - * Reports whether two objects are equal. - * Returns true if the objects are identical. - * @param obj the reference object with which to compare this - * object - * @return true if this object is the same as the - * obj argument; false otherwise + * Reports whether two objects are equal. Returns {@code true} if the + * objects are identical. + * + * @param obj the reference object with which to compare this object + * @return {@code true} if this object is the same as the {@code obj} + * argument; {@code false} otherwise */ public final boolean equals(Object obj) { return super.equals(obj); } - /** * Finalizes the hashcode method. */ @@ -341,7 +305,6 @@ public interface MidiDevice extends AutoCloseable { return super.hashCode(); } - /** * Obtains the name of the device. * @@ -351,43 +314,40 @@ public interface MidiDevice extends AutoCloseable { return name; } - /** * Obtains the name of the company who supplies the device. + * * @return device the vendor's name */ public final String getVendor() { return vendor; } - /** * Obtains the description of the device. + * * @return a description of the device */ public final String getDescription() { return description; } - /** * Obtains the version of the device. + * * @return textual version information for the device. */ public final String getVersion() { return version; } - /** * Provides a string representation of the device information. - + * * @return a description of the info object */ public final String toString() { return name; } } // class Info - - } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDeviceReceiver.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDeviceReceiver.java index 550c7a4ccb8..569850836e1 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDeviceReceiver.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDeviceReceiver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 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 @@ -26,16 +26,18 @@ package javax.sound.midi; /** - *

    {@code MidiDeviceReceiver} is a {@code Receiver} which represents - * a MIDI input connector of a {@code MidiDevice} - * (see {@link MidiDevice#getReceiver()}). + * {@code MidiDeviceReceiver} is a {@code Receiver} which represents a MIDI + * input connector of a {@code MidiDevice} (see + * {@link MidiDevice#getReceiver()}). * * @since 1.7 */ public interface MidiDeviceReceiver extends Receiver { + /** * Obtains a MidiDevice object which is an owner of this Receiver. + * * @return a MidiDevice object which is an owner of this Receiver */ - public MidiDevice getMidiDevice(); + MidiDevice getMidiDevice(); } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDeviceTransmitter.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDeviceTransmitter.java index 730628c5e8d..aaf7aba72d3 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDeviceTransmitter.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiDeviceTransmitter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,10 @@ package javax.sound.midi; - /** - *

    {@code MidiDeviceTransmitter} is a {@code Transmitter} which represents - * a MIDI input connector of a {@code MidiDevice} - * (see {@link MidiDevice#getTransmitter()}). + * {@code MidiDeviceTransmitter} is a {@code Transmitter} which represents a + * MIDI input connector of a {@code MidiDevice} (see + * {@link MidiDevice#getTransmitter()}). * * @since 1.7 */ @@ -37,7 +36,8 @@ public interface MidiDeviceTransmitter extends Transmitter { /** * Obtains a MidiDevice object which is an owner of this Transmitter. + * * @return a MidiDevice object which is an owner of this Transmitter */ - public MidiDevice getMidiDevice(); + MidiDevice getMidiDevice(); } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiEvent.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiEvent.java index b5f4c5ca08d..caf6e7936ad 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiEvent.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiEvent.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 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 @@ -26,41 +26,35 @@ package javax.sound.midi; /** - * MIDI events contain a MIDI message and a corresponding time-stamp - * expressed in ticks, and can represent the MIDI event information - * stored in a MIDI file or a {@link Sequence} object. The - * duration of a tick is specified by the timing information contained - * in the MIDI file or Sequence object. + * MIDI events contain a MIDI message and a corresponding time-stamp expressed + * in ticks, and can represent the MIDI event information stored in a MIDI file + * or a {@link Sequence} object. The duration of a tick is specified by the + * timing information contained in the MIDI file or {@code Sequence} object. *

    - * In Java Sound, MidiEvent objects are typically contained in a - * {@link Track}, and Tracks are likewise - * contained in a Sequence. - * + * In Java Sound, {@code MidiEvent} objects are typically contained in a + * {@link Track}, and {@code Tracks} are likewise contained in a + * {@code Sequence}. * * @author David Rivas * @author Kara Kytle */ public class MidiEvent { - - // Instance variables - /** * The MIDI message for this event. */ private final MidiMessage message; - /** * The tick value for this event. */ private long tick; - /** - * Constructs a new MidiEvent. - * @param message the MIDI message contained in the event - * @param tick the time-stamp for the event, in MIDI ticks + * Constructs a new {@code MidiEvent}. + * + * @param message the MIDI message contained in the event + * @param tick the time-stamp for the event, in MIDI ticks */ public MidiEvent(MidiMessage message, long tick) { @@ -70,24 +64,25 @@ public class MidiEvent { /** * Obtains the MIDI message contained in the event. + * * @return the MIDI message */ public MidiMessage getMessage() { return message; } - /** - * Sets the time-stamp for the event, in MIDI ticks - * @param tick the new time-stamp, in MIDI ticks + * Sets the time-stamp for the event, in MIDI ticks. + * + * @param tick the new time-stamp, in MIDI ticks */ public void setTick(long tick) { this.tick = tick; } - /** - * Obtains the time-stamp for the event, in MIDI ticks + * Obtains the time-stamp for the event, in MIDI ticks. + * * @return the time-stamp for the event, in MIDI ticks */ public long getTick() { diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiFileFormat.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiFileFormat.java index c34bb6d1900..474881571c4 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiFileFormat.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiFileFormat.java @@ -25,29 +25,23 @@ package javax.sound.midi; -import java.io.InputStream; -import java.io.IOException; import java.util.Collections; import java.util.HashMap; import java.util.Map; - /** - * A MidiFileFormat object encapsulates a MIDI file's - * type, as well as its length and timing information. - * - *

    A MidiFileFormat object can - * include a set of properties. A property is a pair of key and value: - * the key is of type String, the associated property - * value is an arbitrary object. - * Properties specify additional informational - * meta data (like a author, or copyright). - * Properties are optional information, and file reader and file - * writer implementations are not required to provide or - * recognize properties. - * - *

    The following table lists some common properties that should - * be used in implementations: + * A {@code MidiFileFormat} object encapsulates a MIDI file's type, as well as + * its length and timing information. + *

    + * A {@code MidiFileFormat} object can include a set of properties. A property + * is a pair of key and value: the key is of type {@code String}, the associated + * property value is an arbitrary object. Properties specify additional + * informational meta data (like a author, or copyright). Properties are + * optional information, and file reader and file writer implementations are not + * required to provide or recognize properties. + *

    + * The following table lists some common properties that should be used in + * implementations: * * @@ -83,24 +77,21 @@ import java.util.Map; * *
    MIDI File Format Properties
    * - * @see MidiSystem#getMidiFileFormat(java.io.File) - * @see Sequencer#setSequence(java.io.InputStream stream) - * * @author Kara Kytle * @author Florian Bomers + * @see MidiSystem#getMidiFileFormat(java.io.File) + * @see Sequencer#setSequence(java.io.InputStream stream) */ - public class MidiFileFormat { - /** * Represents unknown length. + * * @see #getByteLength * @see #getMicrosecondLength */ public static final int UNKNOWN_LENGTH = -1; - /** * The type of MIDI file. */ @@ -132,19 +123,22 @@ public class MidiFileFormat { */ protected long microsecondLength; - - /** The set of properties */ + /** + * The set of properties. + */ private HashMap properties; - /** - * Constructs a MidiFileFormat. + * Constructs a {@code MidiFileFormat}. * - * @param type the MIDI file type (0, 1, or 2) - * @param divisionType the timing division type (PPQ or one of the SMPTE types) - * @param resolution the timing resolution - * @param bytes the length of the MIDI file in bytes, or UNKNOWN_LENGTH if not known - * @param microseconds the duration of the file in microseconds, or UNKNOWN_LENGTH if not known + * @param type the MIDI file type (0, 1, or 2) + * @param divisionType the timing division type (PPQ or one of the SMPTE + * types) + * @param resolution the timing resolution + * @param bytes the length of the MIDI file in bytes, or UNKNOWN_LENGTH if + * not known + * @param microseconds the duration of the file in microseconds, or + * UNKNOWN_LENGTH if not known * @see #UNKNOWN_LENGTH * @see Sequence#PPQ * @see Sequence#SMPTE_24 @@ -162,21 +156,18 @@ public class MidiFileFormat { this.properties = null; } - /** - * Construct a MidiFileFormat with a set of properties. - * - * @param type the MIDI file type (0, 1, or 2) - * @param divisionType the timing division type - * (PPQ or one of the SMPTE types) - * @param resolution the timing resolution - * @param bytes the length of the MIDI file in bytes, - * or UNKNOWN_LENGTH if not known - * @param microseconds the duration of the file in microseconds, - * or UNKNOWN_LENGTH if not known - * @param properties a Map<String,Object> object - * with properties + * Construct a {@code MidiFileFormat} with a set of properties. * + * @param type the MIDI file type (0, 1, or 2) + * @param divisionType the timing division type (PPQ or one of the SMPTE + * types) + * @param resolution the timing resolution + * @param bytes the length of the MIDI file in bytes, or UNKNOWN_LENGTH if + * not known + * @param microseconds the duration of the file in microseconds, or + * UNKNOWN_LENGTH if not known + * @param properties a {@code Map} object with properties * @see #UNKNOWN_LENGTH * @see Sequence#PPQ * @see Sequence#SMPTE_24 @@ -192,10 +183,9 @@ public class MidiFileFormat { this.properties = new HashMap(properties); } - - /** * Obtains the MIDI file type. + * * @return the file's type (0, 1, or 2) */ public int getType() { @@ -206,7 +196,6 @@ public class MidiFileFormat { * Obtains the timing division type for the MIDI file. * * @return the division type (PPQ or one of the SMPTE types) - * * @see Sequence#Sequence(float, int) * @see Sequence#PPQ * @see Sequence#SMPTE_24 @@ -219,11 +208,10 @@ public class MidiFileFormat { return divisionType; } - /** - * Obtains the timing resolution for the MIDI file. - * If the division type is PPQ, the resolution is specified in ticks per beat. - * For SMTPE timing, the resolution is specified in ticks per frame. + * Obtains the timing resolution for the MIDI file. If the division type is + * PPQ, the resolution is specified in ticks per beat. For SMTPE timing, the + * resolution is specified in ticks per frame. * * @return the number of ticks per beat (PPQ) or per frame (SMPTE) * @see #getDivisionType @@ -233,9 +221,9 @@ public class MidiFileFormat { return resolution; } - /** * Obtains the length of the MIDI file, expressed in 8-bit bytes. + * * @return the number of bytes in the file, or UNKNOWN_LENGTH if not known * @see #UNKNOWN_LENGTH */ @@ -245,7 +233,9 @@ public class MidiFileFormat { /** * Obtains the length of the MIDI file, expressed in microseconds. - * @return the file's duration in microseconds, or UNKNOWN_LENGTH if not known + * + * @return the file's duration in microseconds, or UNKNOWN_LENGTH if not + * known * @see Sequence#getMicrosecondLength() * @see #getByteLength * @see #UNKNOWN_LENGTH @@ -255,14 +245,11 @@ public class MidiFileFormat { } /** - * Obtain an unmodifiable map of properties. - * The concept of properties is further explained in - * the {@link MidiFileFormat class description}. - * - * @return a Map<String,Object> object containing - * all properties. If no properties are recognized, an empty map is - * returned. + * Obtain an unmodifiable map of properties. The concept of properties is + * further explained in the {@link MidiFileFormat class description}. * + * @return a {@code Map} object containing all properties. If + * no properties are recognized, an empty map is returned. * @see #getProperty(String) * @since 1.5 */ @@ -277,20 +264,16 @@ public class MidiFileFormat { return Collections.unmodifiableMap(ret); } - /** - * Obtain the property value specified by the key. - * The concept of properties is further explained in - * the {@link MidiFileFormat class description}. - * - *

    If the specified property is not defined for a - * particular file format, this method returns - * null. - * - * @param key the key of the desired property - * @return the value of the property with the specified key, - * or null if the property does not exist. + * Obtain the property value specified by the key. The concept of properties + * is further explained in the {@link MidiFileFormat class description}. + *

    + * If the specified property is not defined for a particular file format, + * this method returns {@code null}. * + * @param key the key of the desired property + * @return the value of the property with the specified key, or {@code null} + * if the property does not exist * @see #properties() * @since 1.5 */ @@ -300,6 +283,4 @@ public class MidiFileFormat { } return properties.get(key); } - - } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiMessage.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiMessage.java index 728d654cea8..0633c32f72b 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiMessage.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,83 +26,76 @@ package javax.sound.midi; /** - * MidiMessage is the base class for MIDI messages. They include - * not only the standard MIDI messages that a synthesizer can respond to, but also - * "meta-events" that can be used by sequencer programs. There are meta-events + * {@code MidiMessage} is the base class for MIDI messages. They include not + * only the standard MIDI messages that a synthesizer can respond to, but also + * "meta-events" that can be used by sequencer programs. There are meta-events * for such information as lyrics, copyrights, tempo indications, time and key - * signatures, markers, etc. For more information, see the Standard MIDI Files 1.0 - * specification, which is part of the Complete MIDI 1.0 Detailed Specification - * published by the MIDI Manufacturer's Association + * signatures, markers, etc. For more information, see the Standard MIDI Files + * 1.0 specification, which is part of the Complete MIDI 1.0 Detailed + * Specification published by the MIDI Manufacturer's Association * (http://www.midi.org). *

    - * The base MidiMessage class provides access to three types of + * The base {@code MidiMessage} class provides access to three types of * information about a MIDI message: *

      *
    • The messages's status byte
    • - *
    • The total length of the message in bytes (the status byte plus any data bytes)
    • + *
    • The total length of the message in bytes (the status byte plus any data + * bytes)
    • *
    • A byte array containing the complete message
    • *
    * - * MidiMessage includes methods to get, but not set, these values. + * {@code MidiMessage} includes methods to get, but not set, these values. * Setting them is a subclass responsibility. *

    - * - * The MIDI standard expresses MIDI data in bytes. However, because - * JavaTM uses signed bytes, the Java Sound API uses integers - * instead of bytes when expressing MIDI data. For example, the - * {@link #getStatus()} method of - * MidiMessage returns MIDI status bytes as integers. If you are - * processing MIDI data that originated outside Java Sound and now - * is encoded as signed bytes, the bytes can - * can be converted to integers using this conversion: + * The MIDI standard expresses MIDI data in + * bytes. However, because JavaTM uses signed bytes, the Java Sound + * API uses integers instead of bytes when expressing MIDI data. For example, + * the {@link #getStatus()} method of {@code MidiMessage} returns MIDI status + * bytes as integers. If you are processing MIDI data that originated outside + * Java Sound and now is encoded as signed bytes, the bytes can can be + * converted to integers using this conversion: + * *

    {@code int i = (int)(byte & 0xFF)}
    *

    - * If you simply need to pass a known MIDI byte value as a method parameter, - * it can be expressed directly as an integer, using (for example) decimal or - * hexadecimal notation. For instance, to pass the "active sensing" status byte + * If you simply need to pass a known MIDI byte value as a method parameter, it + * can be expressed directly as an integer, using (for example) decimal or + * hexadecimal notation. For instance, to pass the "active sensing" status byte * as the first argument to ShortMessage's - * {@link ShortMessage#setMessage(int) setMessage(int)} - * method, you can express it as 254 or 0xFE. - * - * @see Track - * @see Sequence - * @see Receiver + * {@link ShortMessage#setMessage(int) setMessage(int)} method, you can express + * it as 254 or 0xFE. * * @author David Rivas * @author Kara Kytle + * @see Track + * @see Sequence + * @see Receiver */ - public abstract class MidiMessage implements Cloneable { - // Instance variables - /** - * The MIDI message data. The first byte is the status - * byte for the message; subsequent bytes up to the length - * of the message are data bytes for this message. + * The MIDI message data. The first byte is the status byte for the message; + * subsequent bytes up to the length of the message are data bytes for this + * message. + * * @see #getLength */ protected byte[] data; - /** - * The number of bytes in the MIDI message, including the - * status byte and any data bytes. + * The number of bytes in the MIDI message, including the status byte and + * any data bytes. + * * @see #getLength */ protected int length = 0; - /** - * Constructs a new MidiMessage. This protected - * constructor is called by concrete subclasses, which should - * ensure that the data array specifies a complete, valid MIDI - * message. - * - * @param data an array of bytes containing the complete message. - * The message data may be changed using the setMessage - * method. + * Constructs a new {@code MidiMessage}. This protected constructor is + * called by concrete subclasses, which should ensure that the data array + * specifies a complete, valid MIDI message. * + * @param data an array of bytes containing the complete message. The + * message data may be changed using the {@code setMessage} method. * @see #setMessage */ protected MidiMessage(byte[] data) { @@ -112,20 +105,21 @@ public abstract class MidiMessage implements Cloneable { } } - /** - * Sets the data for the MIDI message. This protected - * method is called by concrete subclasses, which should - * ensure that the data array specifies a complete, valid MIDI - * message. + * Sets the data for the MIDI message. This protected method is called by + * concrete subclasses, which should ensure that the data array specifies a + * complete, valid MIDI message. * - * @param data the data bytes in the MIDI message - * @param length the number of bytes in the data byte array - * @throws InvalidMidiDataException if the parameter values do not specify a valid MIDI meta message + * @param data the data bytes in the MIDI message + * @param length the number of bytes in the data byte array + * @throws InvalidMidiDataException if the parameter values do not specify a + * valid MIDI meta message */ - protected void setMessage(byte[] data, int length) throws InvalidMidiDataException { + protected void setMessage(byte[] data, int length) + throws InvalidMidiDataException { if (length < 0 || (length > 0 && length > data.length)) { - throw new IndexOutOfBoundsException("length out of bounds: "+length); + throw new IndexOutOfBoundsException( + "length out of bounds: " + length); } this.length = length; @@ -135,16 +129,14 @@ public abstract class MidiMessage implements Cloneable { System.arraycopy(data, 0, this.data, 0, length); } - /** - * Obtains the MIDI message data. The first byte of the returned byte - * array is the status byte of the message. Any subsequent bytes up to - * the length of the message are data bytes. The byte array may have a - * length which is greater than that of the actual message; the total - * length of the message in bytes is reported by the {@link #getLength} - * method. + * Obtains the MIDI message data. The first byte of the returned byte array + * is the status byte of the message. Any subsequent bytes up to the length + * of the message are data bytes. The byte array may have a length which is + * greater than that of the actual message; the total length of the message + * in bytes is reported by the {@link #getLength} method. * - * @return the byte array containing the complete MidiMessage data + * @return the byte array containing the complete {@code MidiMessage} data */ public byte[] getMessage() { byte[] returnedArray = new byte[length]; @@ -152,12 +144,11 @@ public abstract class MidiMessage implements Cloneable { return returnedArray; } - /** - * Obtains the status byte for the MIDI message. The status "byte" is + * Obtains the status byte for the MIDI message. The status "byte" is * represented as an integer; see the - * discussion in the - * MidiMessage class description. + * discussion in the {@code MidiMessage} + * class description. * * @return the integer representation of this event's status byte */ @@ -168,13 +159,11 @@ public abstract class MidiMessage implements Cloneable { return 0; } - /** - * Obtains the total length of the MIDI message in bytes. A - * MIDI message consists of one status byte and zero or more - * data bytes. The return value ranges from 1 for system real-time messages, - * to 2 or 3 for channel messages, to any value for meta and system - * exclusive messages. + * Obtains the total length of the MIDI message in bytes. A MIDI message + * consists of one status byte and zero or more data bytes. The return value + * ranges from 1 for system real-time messages, to 2 or 3 for channel + * messages, to any value for meta and system exclusive messages. * * @return the length of the message in bytes */ @@ -182,11 +171,11 @@ public abstract class MidiMessage implements Cloneable { return length; } - /** - * Creates a new object of the same class and with the same contents - * as this object. - * @return a clone of this instance. + * Creates a new object of the same class and with the same contents as this + * object. + * + * @return a clone of this instance */ public abstract Object clone(); } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java index 635dc54ce7a..9f790fd0f01 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiSystem.java @@ -25,59 +25,52 @@ package javax.sound.midi; -import java.io.FileInputStream; import java.io.File; +import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.io.IOException; - +import java.net.URL; import java.util.ArrayList; import java.util.HashSet; import java.util.Iterator; import java.util.List; +import java.util.Properties; import java.util.Set; -import java.net.URL; - -import javax.sound.midi.spi.MidiFileWriter; -import javax.sound.midi.spi.MidiFileReader; -import javax.sound.midi.spi.SoundbankReader; import javax.sound.midi.spi.MidiDeviceProvider; +import javax.sound.midi.spi.MidiFileReader; +import javax.sound.midi.spi.MidiFileWriter; +import javax.sound.midi.spi.SoundbankReader; -import com.sun.media.sound.JDK13Services; -import com.sun.media.sound.ReferenceCountingDevice; import com.sun.media.sound.AutoConnectSequencer; +import com.sun.media.sound.JDK13Services; import com.sun.media.sound.MidiDeviceReceiverEnvelope; import com.sun.media.sound.MidiDeviceTransmitterEnvelope; - +import com.sun.media.sound.ReferenceCountingDevice; /** - * The MidiSystem class provides access to the installed MIDI - * system resources, including devices such as synthesizers, sequencers, and - * MIDI input and output ports. A typical simple MIDI application might - * begin by invoking one or more MidiSystem methods to learn - * what devices are installed and to obtain the ones needed in that - * application. + * The {@code MidiSystem} class provides access to the installed MIDI system + * resources, including devices such as synthesizers, sequencers, and MIDI input + * and output ports. A typical simple MIDI application might begin by invoking + * one or more {@code MidiSystem} methods to learn what devices are installed + * and to obtain the ones needed in that application. *

    - * The class also has methods for reading files, streams, and URLs that - * contain standard MIDI file data or soundbanks. You can query the - * MidiSystem for the format of a specified MIDI file. + * The class also has methods for reading files, streams, and URLs that contain + * standard MIDI file data or soundbanks. You can query the {@code MidiSystem} + * for the format of a specified MIDI file. *

    - * You cannot instantiate a MidiSystem; all the methods are - * static. - * - *

    Properties can be used to specify default MIDI devices. - * Both system properties and a properties file are considered. - * The sound.properties properties file is read from - * an implementation-specific location (typically it is the lib - * directory in the Java installation directory). - * If a property exists both as a system property and in the - * properties file, the system property takes precedence. If none is - * specified, a suitable default is chosen among the available devices. - * The syntax of the properties file is specified in - * {@link java.util.Properties#load(InputStream) Properties.load}. The - * following table lists the available property keys and which methods - * consider them: + * You cannot instantiate a {@code MidiSystem}; all the methods are static. + *

    + * Properties can be used to specify default MIDI devices. Both system + * properties and a properties file are considered. The "sound.properties" + * properties file is read from an implementation-specific location (typically + * it is the {@code lib} directory in the Java installation directory). If a + * property exists both as a system property and in the properties file, the + * system property takes precedence. If none is specified, a suitable default is + * chosen among the available devices. The syntax of the properties file is + * specified in {@link Properties#load(InputStream) Properties.load}. The + * following table lists the available property keys and which methods consider + * them: * * * @@ -87,80 +80,64 @@ import com.sun.media.sound.MidiDeviceTransmitterEnvelope; * * * - * + * * * * * - * + * * * * * - * + * * * * * - * + * * * * *
    MIDI System Property Keys
    Affected Method
    javax.sound.midi.Receiver{@code javax.sound.midi.Receiver}{@link Receiver}{@link #getReceiver}
    javax.sound.midi.Sequencer{@code javax.sound.midi.Sequencer}{@link Sequencer}{@link #getSequencer}
    javax.sound.midi.Synthesizer{@code javax.sound.midi.Synthesizer}{@link Synthesizer}{@link #getSynthesizer}
    javax.sound.midi.Transmitter{@code javax.sound.midi.Transmitter}{@link Transmitter}{@link #getTransmitter}
    * - * The property value consists of the provider class name - * and the device name, separated by the hash mark ("#"). - * The provider class name is the fully-qualified - * name of a concrete {@link javax.sound.midi.spi.MidiDeviceProvider - * MIDI device provider} class. The device name is matched against - * the String returned by the getName - * method of MidiDevice.Info. - * Either the class name, or the device name may be omitted. - * If only the class name is specified, the trailing hash mark - * is optional. - * - *

    If the provider class is specified, and it can be - * successfully retrieved from the installed providers, - * the list of - * MidiDevice.Info objects is retrieved - * from the provider. Otherwise, or when these devices - * do not provide a subsequent match, the list is retrieved - * from {@link #getMidiDeviceInfo} to contain - * all available MidiDevice.Info objects. - * - *

    If a device name is specified, the resulting list of - * MidiDevice.Info objects is searched: - * the first one with a matching name, and whose - * MidiDevice implements the - * respective interface, will be returned. - * If no matching MidiDevice.Info object - * is found, or the device name is not specified, - * the first suitable device from the resulting - * list will be returned. For Sequencer and Synthesizer, - * a device is suitable if it implements the respective - * interface; whereas for Receiver and Transmitter, a device is - * suitable if it - * implements neither Sequencer nor Synthesizer and provides - * at least one Receiver or Transmitter, respectively. - * - * For example, the property javax.sound.midi.Receiver - * with a value - * "com.sun.media.sound.MidiProvider#SunMIDI1" - * will have the following consequences when - * getReceiver is called: - * if the class com.sun.media.sound.MidiProvider exists - * in the list of installed MIDI device providers, - * the first Receiver device with name - * "SunMIDI1" will be returned. If it cannot - * be found, the first Receiver from that provider - * will be returned, regardless of name. - * If there is none, the first Receiver with name - * "SunMIDI1" in the list of all devices - * (as returned by getMidiDeviceInfo) will be returned, - * or, if not found, the first Receiver that can - * be found in the list of all devices is returned. - * If that fails, too, a MidiUnavailableException - * is thrown. + * The property value consists of the provider class name and the device name, + * separated by the hash mark ("#"). The provider class name is the + * fully-qualified name of a concrete + * {@link MidiDeviceProvider MIDI device provider} class. The device name is + * matched against the {@code String} returned by the {@code getName} method of + * {@code MidiDevice.Info}. Either the class name, or the device name may be + * omitted. If only the class name is specified, the trailing hash mark is + * optional. + *

    + * If the provider class is specified, and it can be successfully retrieved from + * the installed providers, the list of {@code MidiDevice.Info} objects is + * retrieved from the provider. Otherwise, or when these devices do not provide + * a subsequent match, the list is retrieved from {@link #getMidiDeviceInfo} to + * contain all available {@code MidiDevice.Info} objects. + *

    + * If a device name is specified, the resulting list of {@code MidiDevice.Info} + * objects is searched: the first one with a matching name, and whose + * {@code MidiDevice} implements the respective interface, will be returned. If + * no matching {@code MidiDevice.Info} object is found, or the device name is + * not specified, the first suitable device from the resulting list will be + * returned. For Sequencer and Synthesizer, a device is suitable if it + * implements the respective interface; whereas for Receiver and Transmitter, a + * device is suitable if it implements neither Sequencer nor Synthesizer and + * provides at least one Receiver or Transmitter, respectively. + *

    + * For example, the property {@code javax.sound.midi.Receiver} with a value + * {@code "com.sun.media.sound.MidiProvider#SunMIDI1"} will have the following + * consequences when {@code getReceiver} is called: if the class + * {@code com.sun.media.sound.MidiProvider} exists in the list of installed MIDI + * device providers, the first {@code Receiver} device with name + * {@code "SunMIDI1"} will be returned. If it cannot be found, the first + * {@code Receiver} from that provider will be returned, regardless of name. If + * there is none, the first {@code Receiver} with name {@code "SunMIDI1"} in the + * list of all devices (as returned by {@code getMidiDeviceInfo}) will be + * returned, or, if not found, the first {@code Receiver} that can be found in + * the list of all devices is returned. If that fails, too, a + * {@code MidiUnavailableException} is thrown. * * @author Kara Kytle * @author Florian Bomers @@ -174,17 +151,15 @@ public class MidiSystem { private MidiSystem() { } - /** - * Obtains an array of information objects representing - * the set of all MIDI devices available on the system. - * A returned information object can then be used to obtain the - * corresponding device object, by invoking + * Obtains an array of information objects representing the set of all MIDI + * devices available on the system. A returned information object can then + * be used to obtain the corresponding device object, by invoking * {@link #getMidiDevice(MidiDevice.Info) getMidiDevice}. * - * @return an array of MidiDevice.Info objects, one - * for each installed MIDI device. If no such devices are installed, - * an array of length 0 is returned. + * @return an array of {@code MidiDevice.Info} objects, one for each + * installed MIDI device. If no such devices are installed, an array + * of length 0 is returned. */ public static MidiDevice.Info[] getMidiDeviceInfo() { List allInfos = new ArrayList<>(); @@ -201,16 +176,15 @@ public class MidiSystem { return infosArray; } - /** * Obtains the requested MIDI device. * - * @param info a device information object representing the desired device. + * @param info a device information object representing the desired device * @return the requested device * @throws MidiUnavailableException if the requested device is not available - * due to resource restrictions - * @throws IllegalArgumentException if the info object does not represent - * a MIDI device installed on the system + * due to resource restrictions + * @throws IllegalArgumentException if the info object does not represent a + * MIDI device installed on the system * @see #getMidiDeviceInfo */ public static MidiDevice getMidiDevice(MidiDevice.Info info) throws MidiUnavailableException { @@ -226,44 +200,38 @@ public class MidiSystem { throw new IllegalArgumentException("Requested device not installed: " + info); } - /** - * Obtains a MIDI receiver from an external MIDI port - * or other default device. - * The returned receiver always implements - * the {@code MidiDeviceReceiver} interface. - * - *

    If the system property - * javax.sound.midi.Receiver - * is defined or it is defined in the file "sound.properties", - * it is used to identify the device that provides the default receiver. - * For details, refer to the {@link MidiSystem class description}. - * - * If a suitable MIDI port is not available, the Receiver is - * retrieved from an installed synthesizer. - * - *

    If a native receiver provided by the default device does not implement - * the {@code MidiDeviceReceiver} interface, it will be wrapped in a - * wrapper class that implements the {@code MidiDeviceReceiver} interface. - * The corresponding {@code Receiver} method calls will be forwarded - * to the native receiver. - * - *

    If this method returns successfully, the {@link - * javax.sound.midi.MidiDevice MidiDevice} the - * Receiver belongs to is opened implicitly, if it is - * not already open. It is possible to close an implicitly opened - * device by calling {@link javax.sound.midi.Receiver#close close} - * on the returned Receiver. All open Receiver - * instances have to be closed in order to release system resources - * hold by the MidiDevice. For a - * detailed description of open/close behaviour see the class - * description of {@link javax.sound.midi.MidiDevice MidiDevice}. - * + * Obtains a MIDI receiver from an external MIDI port or other default + * device. The returned receiver always implements the + * {@code MidiDeviceReceiver} interface. + *

    + * If the system property {@code javax.sound.midi.Receiver} is defined or it + * is defined in the file "sound.properties", it is used to identify the + * device that provides the default receiver. For details, refer to the + * {@link MidiSystem class description}. + *

    + * If a suitable MIDI port is not available, the Receiver is retrieved from + * an installed synthesizer. + *

    + * If a native receiver provided by the default device does not implement + * the {@code MidiDeviceReceiver} interface, it will be wrapped in a wrapper + * class that implements the {@code MidiDeviceReceiver} interface. The + * corresponding {@code Receiver} method calls will be forwarded to the + * native receiver. + *

    + * If this method returns successfully, the {@link MidiDevice MidiDevice} + * the {@code Receiver} belongs to is opened implicitly, if it is not + * already open. It is possible to close an implicitly opened device by + * calling {@link Receiver#close close} on the returned {@code Receiver}. + * All open {@code Receiver} instances have to be closed in order to release + * system resources hold by the {@code MidiDevice}. For a detailed + * description of open/close behaviour see the class description of + * {@link MidiDevice MidiDevice}. * * @return the default MIDI receiver - * @throws MidiUnavailableException if the default receiver is not - * available due to resource restrictions, - * or no device providing receivers is installed in the system + * @throws MidiUnavailableException if the default receiver is not available + * due to resource restrictions, or no device providing receivers is + * installed in the system */ public static Receiver getReceiver() throws MidiUnavailableException { // may throw MidiUnavailableException @@ -280,41 +248,35 @@ public class MidiSystem { return receiver; } - /** - * Obtains a MIDI transmitter from an external MIDI port - * or other default source. - * The returned transmitter always implements - * the {@code MidiDeviceTransmitter} interface. - * - *

    If the system property - * javax.sound.midi.Transmitter - * is defined or it is defined in the file "sound.properties", - * it is used to identify the device that provides the default transmitter. - * For details, refer to the {@link MidiSystem class description}. - * - *

    If a native transmitter provided by the default device does not implement + * Obtains a MIDI transmitter from an external MIDI port or other default + * source. The returned transmitter always implements the + * {@code MidiDeviceTransmitter} interface. + *

    + * If the system property {@code javax.sound.midi.Transmitter} is defined or + * it is defined in the file "sound.properties", it is used to identify the + * device that provides the default transmitter. For details, refer to the + * {@link MidiSystem class description}. + *

    + * If a native transmitter provided by the default device does not implement * the {@code MidiDeviceTransmitter} interface, it will be wrapped in a - * wrapper class that implements the {@code MidiDeviceTransmitter} interface. - * The corresponding {@code Transmitter} method calls will be forwarded - * to the native transmitter. - * - *

    If this method returns successfully, the {@link - * javax.sound.midi.MidiDevice MidiDevice} the - * Transmitter belongs to is opened implicitly, if it - * is not already open. It is possible to close an implicitly - * opened device by calling {@link - * javax.sound.midi.Transmitter#close close} on the returned - * Transmitter. All open Transmitter - * instances have to be closed in order to release system resources - * hold by the MidiDevice. For a detailed description - * of open/close behaviour see the class description of {@link - * javax.sound.midi.MidiDevice MidiDevice}. + * wrapper class that implements the {@code MidiDeviceTransmitter} + * interface. The corresponding {@code Transmitter} method calls will be + * forwarded to the native transmitter. + *

    + * If this method returns successfully, the {@link MidiDevice MidiDevice} + * the {@code Transmitter} belongs to is opened implicitly, if it is not + * already open. It is possible to close an implicitly opened device by + * calling {@link Transmitter#close close} on the returned + * {@code Transmitter}. All open {@code Transmitter} instances have to be + * closed in order to release system resources hold by the + * {@code MidiDevice}. For a detailed description of open/close behaviour + * see the class description of {@link MidiDevice MidiDevice}. * * @return the default MIDI transmitter * @throws MidiUnavailableException if the default transmitter is not - * available due to resource restrictions, - * or no device providing transmitters is installed in the system + * available due to resource restrictions, or no device providing + * transmitters is installed in the system */ public static Transmitter getTransmitter() throws MidiUnavailableException { // may throw MidiUnavailableException @@ -331,59 +293,48 @@ public class MidiSystem { return transmitter; } - /** * Obtains the default synthesizer. - * - *

    If the system property - * javax.sound.midi.Synthesizer - * is defined or it is defined in the file "sound.properties", - * it is used to identify the default synthesizer. - * For details, refer to the {@link MidiSystem class description}. + *

    + * If the system property {@code javax.sound.midi.Synthesizer} is defined or + * it is defined in the file "sound.properties", it is used to identify the + * default synthesizer. For details, refer to the + * {@link MidiSystem class description}. * * @return the default synthesizer - * @throws MidiUnavailableException if the synthesizer is not - * available due to resource restrictions, - * or no synthesizer is installed in the system + * @throws MidiUnavailableException if the synthesizer is not available due + * to resource restrictions, or no synthesizer is installed in the + * system */ public static Synthesizer getSynthesizer() throws MidiUnavailableException { // may throw MidiUnavailableException return (Synthesizer) getDefaultDeviceWrapper(Synthesizer.class); } - /** - * Obtains the default Sequencer, connected to - * a default device. - * The returned Sequencer instance is - * connected to the default Synthesizer, - * as returned by {@link #getSynthesizer}. - * If there is no Synthesizer - * available, or the default Synthesizer - * cannot be opened, the sequencer is connected - * to the default Receiver, as returned - * by {@link #getReceiver}. - * The connection is made by retrieving a Transmitter - * instance from the Sequencer and setting its - * Receiver. - * Closing and re-opening the sequencer will restore the - * connection to the default device. - * - *

    This method is equivalent to calling - * getSequencer(true). - * - *

    If the system property - * javax.sound.midi.Sequencer - * is defined or it is defined in the file "sound.properties", - * it is used to identify the default sequencer. - * For details, refer to the {@link MidiSystem class description}. + * Obtains the default {@code Sequencer}, connected to a default device. The + * returned {@code Sequencer} instance is connected to the default + * {@code Synthesizer}, as returned by {@link #getSynthesizer}. If there is + * no {@code Synthesizer} available, or the default {@code Synthesizer} + * cannot be opened, the {@code sequencer} is connected to the default + * {@code Receiver}, as returned by {@link #getReceiver}. The connection is + * made by retrieving a {@code Transmitter} instance from the + * {@code Sequencer} and setting its {@code Receiver}. Closing and + * re-opening the sequencer will restore the connection to the default + * device. + *

    + * This method is equivalent to calling {@code getSequencer(true)}. + *

    + * If the system property {@code javax.sound.midi.Sequencer} is defined or + * it is defined in the file "sound.properties", it is used to identify the + * default sequencer. For details, refer to the + * {@link MidiSystem class description}. * * @return the default sequencer, connected to a default Receiver - * @throws MidiUnavailableException if the sequencer is not - * available due to resource restrictions, - * or there is no Receiver available by any - * installed MidiDevice, - * or no sequencer is installed in the system. + * @throws MidiUnavailableException if the sequencer is not available due to + * resource restrictions, or there is no {@code Receiver} available + * by any installed {@code MidiDevice}, or no sequencer is installed + * in the system * @see #getSequencer(boolean) * @see #getSynthesizer * @see #getReceiver @@ -392,49 +343,37 @@ public class MidiSystem { return getSequencer(true); } - - /** - * Obtains the default Sequencer, optionally - * connected to a default device. - * - *

    If connected is true, the returned - * Sequencer instance is - * connected to the default Synthesizer, - * as returned by {@link #getSynthesizer}. - * If there is no Synthesizer - * available, or the default Synthesizer - * cannot be opened, the sequencer is connected - * to the default Receiver, as returned - * by {@link #getReceiver}. - * The connection is made by retrieving a Transmitter - * instance from the Sequencer and setting its - * Receiver. - * Closing and re-opening the sequencer will restore the + * Obtains the default {@code Sequencer}, optionally connected to a default + * device. + *

    + * If {@code connected} is true, the returned {@code Sequencer} instance is + * connected to the default {@code Synthesizer}, as returned by + * {@link #getSynthesizer}. If there is no {@code Synthesizer} available, or + * the default {@code Synthesizer} cannot be opened, the {@code sequencer} + * is connected to the default {@code Receiver}, as returned by + * {@link #getReceiver}. The connection is made by retrieving a + * {@code Transmitter} instance from the {@code Sequencer} and setting its + * {@code Receiver}. Closing and re-opening the sequencer will restore the * connection to the default device. + *

    + * If {@code connected} is false, the returned {@code Sequencer} instance is + * not connected, it has no open {@code Transmitters}. In order to play the + * sequencer on a MIDI device, or a {@code Synthesizer}, it is necessary to + * get a {@code Transmitter} and set its {@code Receiver}. + *

    + * If the system property {@code javax.sound.midi.Sequencer} is defined or + * it is defined in the file "sound.properties", it is used to identify the + * default sequencer. For details, refer to the + * {@link MidiSystem class description}. * - *

    If connected is false, the returned - * Sequencer instance is not connected, it - * has no open Transmitters. In order to - * play the sequencer on a MIDI device, or a Synthesizer, - * it is necessary to get a Transmitter and set its - * Receiver. - * - *

    If the system property - * javax.sound.midi.Sequencer - * is defined or it is defined in the file "sound.properties", - * it is used to identify the default sequencer. - * For details, refer to the {@link MidiSystem class description}. - * - * @param connected whether or not the returned {@code Sequencer} - * is connected to the default {@code Synthesizer} + * @param connected whether or not the returned {@code Sequencer} is + * connected to the default {@code Synthesizer} * @return the default sequencer - * @throws MidiUnavailableException if the sequencer is not - * available due to resource restrictions, - * or no sequencer is installed in the system, - * or if connected is true, and there is - * no Receiver available by any installed - * MidiDevice + * @throws MidiUnavailableException if the sequencer is not available due to + * resource restrictions, or no sequencer is installed in the + * system, or if {@code connected} is true, and there is no + * {@code Receiver} available by any installed {@code MidiDevice} * @see #getSynthesizer * @see #getReceiver * @since 1.5 @@ -501,23 +440,20 @@ public class MidiSystem { return seq; } - - - /** - * Constructs a MIDI sound bank by reading it from the specified stream. - * The stream must point to - * a valid MIDI soundbank file. In general, MIDI soundbank providers may - * need to read some data from the stream before determining whether they - * support it. These parsers must - * be able to mark the stream, read enough data to determine whether they - * support the stream, and, if not, reset the stream's read pointer to - * its original position. If the input stream does not support this, - * this method may fail with an IOException. - * @param stream the source of the sound bank data. + * Constructs a MIDI sound bank by reading it from the specified stream. The + * stream must point to a valid MIDI soundbank file. In general, MIDI + * soundbank providers may need to read some data from the stream before + * determining whether they support it. These parsers must be able to mark + * the stream, read enough data to determine whether they support the + * stream, and, if not, reset the stream's read pointer to its original + * position. If the input stream does not support this, this method may fail + * with an {@code IOException}. + * + * @param stream the source of the sound bank data * @return the sound bank - * @throws InvalidMidiDataException if the stream does not point to - * valid MIDI soundbank data recognized by the system + * @throws InvalidMidiDataException if the stream does not point to valid + * MIDI soundbank data recognized by the system * @throws IOException if an I/O error occurred when loading the soundbank * @see InputStream#markSupported * @see InputStream#mark @@ -542,15 +478,14 @@ public class MidiSystem { } - /** - * Constructs a Soundbank by reading it from the specified URL. - * The URL must point to a valid MIDI soundbank file. + * Constructs a {@code Soundbank} by reading it from the specified URL. The + * URL must point to a valid MIDI soundbank file. * - * @param url the source of the sound bank data + * @param url the source of the sound bank data * @return the sound bank * @throws InvalidMidiDataException if the URL does not point to valid MIDI - * soundbank data recognized by the system + * soundbank data recognized by the system * @throws IOException if an I/O error occurred when loading the soundbank */ public static Soundbank getSoundbank(URL url) @@ -573,16 +508,14 @@ public class MidiSystem { } - /** - * Constructs a Soundbank by reading it from the specified - * File. - * The File must point to a valid MIDI soundbank file. + * Constructs a {@code Soundbank} by reading it from the specified + * {@code File}. The {@code File} must point to a valid MIDI soundbank file. * - * @param file the source of the sound bank data + * @param file the source of the sound bank data * @return the sound bank - * @throws InvalidMidiDataException if the File does not - * point to valid MIDI soundbank data recognized by the system + * @throws InvalidMidiDataException if the {@code File} does not point to + * valid MIDI soundbank data recognized by the system * @throws IOException if an I/O error occurred when loading the soundbank */ public static Soundbank getSoundbank(File file) @@ -604,35 +537,33 @@ public class MidiSystem { throw new InvalidMidiDataException("cannot get soundbank from stream"); } - - /** * Obtains the MIDI file format of the data in the specified input stream. * The stream must point to valid MIDI file data for a file type recognized * by the system. *

    * This method and/or the code it invokes may need to read some data from - * the stream to determine whether its data format is supported. The - * implementation may therefore - * need to mark the stream, read enough data to determine whether it is in - * a supported format, and reset the stream's read pointer to its original - * position. If the input stream does not permit this set of operations, - * this method may fail with an IOException. + * the stream to determine whether its data format is supported. The + * implementation may therefore need to mark the stream, read enough data to + * determine whether it is in a supported format, and reset the stream's + * read pointer to its original position. If the input stream does not + * permit this set of operations, this method may fail with an + * {@code IOException}. *

    * This operation can only succeed for files of a type which can be parsed - * by an installed file reader. It may fail with an InvalidMidiDataException - * even for valid files if no compatible file reader is installed. It - * will also fail with an InvalidMidiDataException if a compatible file reader - * is installed, but encounters errors while determining the file format. + * by an installed file reader. It may fail with an + * {@code InvalidMidiDataException} even for valid files if no compatible + * file reader is installed. It will also fail with an + * {@code InvalidMidiDataException} if a compatible file reader is + * installed, but encounters errors while determining the file format. * - * @param stream the input stream from which file format information - * should be extracted - * @return an MidiFileFormat object describing the MIDI file - * format + * @param stream the input stream from which file format information should + * be extracted + * @return an {@code MidiFileFormat} object describing the MIDI file format * @throws InvalidMidiDataException if the stream does not point to valid - * MIDI file data recognized by the system + * MIDI file data recognized by the system * @throws IOException if an I/O exception occurs while accessing the - * stream + * stream * @see #getMidiFileFormat(URL) * @see #getMidiFileFormat(File) * @see InputStream#markSupported @@ -661,26 +592,24 @@ public class MidiSystem { } } - /** - * Obtains the MIDI file format of the data in the specified URL. The URL - * must point to valid MIDI file data for a file type recognized - * by the system. + * Obtains the MIDI file format of the data in the specified URL. The URL + * must point to valid MIDI file data for a file type recognized by the + * system. *

    * This operation can only succeed for files of a type which can be parsed - * by an installed file reader. It may fail with an InvalidMidiDataException - * even for valid files if no compatible file reader is installed. It - * will also fail with an InvalidMidiDataException if a compatible file reader - * is installed, but encounters errors while determining the file format. + * by an installed file reader. It may fail with an + * {@code InvalidMidiDataException} even for valid files if no compatible + * file reader is installed. It will also fail with an + * {@code InvalidMidiDataException} if a compatible file reader is + * installed, but encounters errors while determining the file format. * - * @param url the URL from which file format information should be - * extracted - * @return a MidiFileFormat object describing the MIDI file - * format + * @param url the URL from which file format information should be + * extracted + * @return a {@code MidiFileFormat} object describing the MIDI file format * @throws InvalidMidiDataException if the URL does not point to valid MIDI - * file data recognized by the system + * file data recognized by the system * @throws IOException if an I/O exception occurs while accessing the URL - * * @see #getMidiFileFormat(InputStream) * @see #getMidiFileFormat(File) */ @@ -707,26 +636,24 @@ public class MidiSystem { } } - /** - * Obtains the MIDI file format of the specified File. The - * File must point to valid MIDI file data for a file type + * Obtains the MIDI file format of the specified {@code File}. The + * {@code File} must point to valid MIDI file data for a file type * recognized by the system. *

    * This operation can only succeed for files of a type which can be parsed - * by an installed file reader. It may fail with an InvalidMidiDataException - * even for valid files if no compatible file reader is installed. It - * will also fail with an InvalidMidiDataException if a compatible file reader - * is installed, but encounters errors while determining the file format. + * by an installed file reader. It may fail with an + * {@code InvalidMidiDataException} even for valid files if no compatible + * file reader is installed. It will also fail with an + * {@code InvalidMidiDataException} if a compatible file reader is + * installed, but encounters errors while determining the file format. * - * @param file the File from which file format information - * should be extracted - * @return a MidiFileFormat object describing the MIDI file - * format - * @throws InvalidMidiDataException if the File does not point - * to valid MIDI file data recognized by the system + * @param file the {@code File} from which file format information should + * be extracted + * @return a {@code MidiFileFormat} object describing the MIDI file format + * @throws InvalidMidiDataException if the {@code File} does not point to + * valid MIDI file data recognized by the system * @throws IOException if an I/O exception occurs while accessing the file - * * @see #getMidiFileFormat(InputStream) * @see #getMidiFileFormat(URL) */ @@ -753,35 +680,33 @@ public class MidiSystem { } } - /** - * Obtains a MIDI sequence from the specified input stream. The stream must - * point to valid MIDI file data for a file type recognized - * by the system. + * Obtains a MIDI sequence from the specified input stream. The stream must + * point to valid MIDI file data for a file type recognized by the system. *

    - * This method and/or the code it invokes may need to read some data - * from the stream to determine whether - * its data format is supported. The implementation may therefore - * need to mark the stream, read enough data to determine whether it is in - * a supported format, and reset the stream's read pointer to its original - * position. If the input stream does not permit this set of operations, - * this method may fail with an IOException. + * This method and/or the code it invokes may need to read some data from + * the stream to determine whether its data format is supported. The + * implementation may therefore need to mark the stream, read enough data to + * determine whether it is in a supported format, and reset the stream's + * read pointer to its original position. If the input stream does not + * permit this set of operations, this method may fail with an + * {@code IOException}. *

    * This operation can only succeed for files of a type which can be parsed - * by an installed file reader. It may fail with an InvalidMidiDataException - * even for valid files if no compatible file reader is installed. It - * will also fail with an InvalidMidiDataException if a compatible file reader - * is installed, but encounters errors while constructing the Sequence + * by an installed file reader. It may fail with an + * {@code InvalidMidiDataException} even for valid files if no compatible + * file reader is installed. It will also fail with an + * {@code InvalidMidiDataException} if a compatible file reader is + * installed, but encounters errors while constructing the {@code Sequence} * object from the file data. * - * @param stream the input stream from which the Sequence - * should be constructed - * @return a Sequence object based on the MIDI file data - * contained in the input stream - * @throws InvalidMidiDataException if the stream does not point to - * valid MIDI file data recognized by the system - * @throws IOException if an I/O exception occurs while accessing the - * stream + * @param stream the input stream from which the {@code Sequence} should be + * constructed + * @return a {@code Sequence} object based on the MIDI file data contained + * in the input stream + * @throws InvalidMidiDataException if the stream does not point to valid + * MIDI file data recognized by the system + * @throws IOException if an I/O exception occurs while accessing the stream * @see InputStream#markSupported * @see InputStream#mark */ @@ -808,25 +733,23 @@ public class MidiSystem { } } - /** - * Obtains a MIDI sequence from the specified URL. The URL must - * point to valid MIDI file data for a file type recognized - * by the system. + * Obtains a MIDI sequence from the specified URL. The URL must point to + * valid MIDI file data for a file type recognized by the system. *

    * This operation can only succeed for files of a type which can be parsed - * by an installed file reader. It may fail with an InvalidMidiDataException - * even for valid files if no compatible file reader is installed. It - * will also fail with an InvalidMidiDataException if a compatible file reader - * is installed, but encounters errors while constructing the Sequence + * by an installed file reader. It may fail with an + * {@code InvalidMidiDataException} even for valid files if no compatible + * file reader is installed. It will also fail with an + * {@code InvalidMidiDataException} if a compatible file reader is + * installed, but encounters errors while constructing the {@code Sequence} * object from the file data. * - * @param url the URL from which the Sequence should be - * constructed - * @return a Sequence object based on the MIDI file data - * pointed to by the URL + * @param url the URL from which the {@code Sequence} should be constructed + * @return a {@code Sequence} object based on the MIDI file data pointed to + * by the URL * @throws InvalidMidiDataException if the URL does not point to valid MIDI - * file data recognized by the system + * file data recognized by the system * @throws IOException if an I/O exception occurs while accessing the URL */ public static Sequence getSequence(URL url) @@ -852,25 +775,25 @@ public class MidiSystem { } } - /** - * Obtains a MIDI sequence from the specified File. - * The File must point to valid MIDI file data - * for a file type recognized by the system. + * Obtains a MIDI sequence from the specified {@code File}. The {@code File} + * must point to valid MIDI file data for a file type recognized by the + * system. *

    * This operation can only succeed for files of a type which can be parsed - * by an installed file reader. It may fail with an InvalidMidiDataException - * even for valid files if no compatible file reader is installed. It - * will also fail with an InvalidMidiDataException if a compatible file reader - * is installed, but encounters errors while constructing the Sequence + * by an installed file reader. It may fail with an + * {@code InvalidMidiDataException} even for valid files if no compatible + * file reader is installed. It will also fail with an + * {@code InvalidMidiDataException} if a compatible file reader is + * installed, but encounters errors while constructing the {@code Sequence} * object from the file data. * - * @param file the File from which the Sequence - * should be constructed - * @return a Sequence object based on the MIDI file data - * pointed to by the File + * @param file the {@code File} from which the {@code Sequence} should be + * constructed + * @return a {@code Sequence} object based on the MIDI file data pointed to + * by the File * @throws InvalidMidiDataException if the File does not point to valid MIDI - * file data recognized by the system + * file data recognized by the system * @throws IOException if an I/O exception occurs */ public static Sequence getSequence(File file) @@ -896,12 +819,12 @@ public class MidiSystem { } } - /** * Obtains the set of MIDI file types for which file writing support is * provided by the system. - * @return array of unique file types. If no file types are supported, - * an array of length 0 is returned. + * + * @return array of unique file types. If no file types are supported, an + * array of length 0 is returned. */ public static int[] getMidiFileTypes() { @@ -927,13 +850,13 @@ public class MidiSystem { return resultTypes; } - /** * Indicates whether file writing support for the specified MIDI file type * is provided by the system. - * @param fileType the file type for which write capabilities are queried - * @return true if the file type is supported, - * otherwise false + * + * @param fileType the file type for which write capabilities are queried + * @return {@code true} if the file type is supported, otherwise + * {@code false} */ public static boolean isFileTypeSupported(int fileType) { @@ -948,14 +871,13 @@ public class MidiSystem { return false; } - /** * Obtains the set of MIDI file types that the system can write from the * sequence specified. - * @param sequence the sequence for which MIDI file type support - * is queried - * @return the set of unique supported file types. If no file types are supported, - * returns an array of length 0. + * + * @param sequence the sequence for which MIDI file type support is queried + * @return the set of unique supported file types. If no file types are + * supported, returns an array of length 0. */ public static int[] getMidiFileTypes(Sequence sequence) { @@ -981,15 +903,14 @@ public class MidiSystem { return resultTypes; } - /** * Indicates whether a MIDI file of the file type specified can be written * from the sequence indicated. - * @param fileType the file type for which write capabilities - * are queried - * @param sequence the sequence for which file writing support is queried - * @return true if the file type is supported for this - * sequence, otherwise false + * + * @param fileType the file type for which write capabilities are queried + * @param sequence the sequence for which file writing support is queried + * @return {@code true} if the file type is supported for this sequence, + * otherwise {@code false} */ public static boolean isFileTypeSupported(int fileType, Sequence sequence) { @@ -1004,19 +925,20 @@ public class MidiSystem { return false; } - /** * Writes a stream of bytes representing a file of the MIDI file type * indicated to the output stream provided. - * @param in sequence containing MIDI data to be written to the file - * @param fileType the file type of the file to be written to the output stream - * @param out stream to which the file data should be written + * + * @param in sequence containing MIDI data to be written to the file + * @param fileType the file type of the file to be written to the output + * stream + * @param out stream to which the file data should be written * @return the number of bytes written to the output stream * @throws IOException if an I/O exception occurs * @throws IllegalArgumentException if the file format is not supported by - * the system + * the system * @see #isFileTypeSupported(int, Sequence) - * @see #getMidiFileTypes(Sequence) + * @see #getMidiFileTypes(Sequence) */ public static int write(Sequence in, int fileType, OutputStream out) throws IOException { @@ -1038,19 +960,19 @@ public class MidiSystem { return bytesWritten; } - /** * Writes a stream of bytes representing a file of the MIDI file type * indicated to the external file provided. - * @param in sequence containing MIDI data to be written to the file - * @param type the file type of the file to be written to the output stream - * @param out external file to which the file data should be written + * + * @param in sequence containing MIDI data to be written to the file + * @param type the file type of the file to be written to the output stream + * @param out external file to which the file data should be written * @return the number of bytes written to the file * @throws IOException if an I/O exception occurs - * @throws IllegalArgumentException if the file type is not supported by - * the system + * @throws IllegalArgumentException if the file type is not supported by the + * system * @see #isFileTypeSupported(int, Sequence) - * @see #getMidiFileTypes(Sequence) + * @see #getMidiFileTypes(Sequence) */ public static int write(Sequence in, int type, File out) throws IOException { @@ -1072,8 +994,6 @@ public class MidiSystem { return bytesWritten; } - - // HELPER METHODS @SuppressWarnings("unchecked") private static List getMidiDeviceProviders() { @@ -1095,19 +1015,16 @@ public class MidiSystem { return (List) getProviders(MidiFileReader.class); } - - /** Attempts to locate and return a default MidiDevice of the specified - * type. - * + /** + * Attempts to locate and return a default MidiDevice of the specified type. * This method wraps {@link #getDefaultDevice}. It catches the - * IllegalArgumentException thrown by - * getDefaultDevice and instead throws a - * MidiUnavailableException, with the catched + * {@code IllegalArgumentException} thrown by {@code getDefaultDevice} and + * instead throws a {@code MidiUnavailableException}, with the catched * exception chained. * - * @param deviceClass The requested device type, one of Synthesizer.class, - * Sequencer.class, Receiver.class or Transmitter.class. - * @throws MidiUnavalableException on failure. + * @param deviceClass The requested device type, one of Synthesizer.class, + * Sequencer.class, Receiver.class or Transmitter.class + * @throws MidiUnavailableException on failure */ private static MidiDevice getDefaultDeviceWrapper(Class deviceClass) throws MidiUnavailableException{ @@ -1120,13 +1037,12 @@ public class MidiSystem { } } - - /** Attempts to locate and return a default MidiDevice of the specified - * type. + /** + * Attempts to locate and return a default MidiDevice of the specified type. * - * @param deviceClass The requested device type, one of Synthesizer.class, - * Sequencer.class, Receiver.class or Transmitter.class. - * @throws IllegalArgumentException on failure. + * @param deviceClass The requested device type, one of Synthesizer.class, + * Sequencer.class, Receiver.class or Transmitter.class + * @throws IllegalArgumentException on failure */ private static MidiDevice getDefaultDevice(Class deviceClass) { List providers = getMidiDeviceProviders(); @@ -1169,16 +1085,15 @@ public class MidiSystem { throw new IllegalArgumentException("Requested device not installed"); } - - - /** Return a MidiDeviceProcider of a given class from the list of - MidiDeviceProviders. - - @param providerClassName The class name of the provider to be returned. - @param provider The list of MidiDeviceProviders that is searched. - @return A MidiDeviceProvider of the requested class, or null if none - is found. - */ + /** + * Return a MidiDeviceProvider of a given class from the list of + * MidiDeviceProviders. + * + * @param providerClassName The class name of the provider to be returned + * @param providers The list of MidiDeviceProviders that is searched + * @return A MidiDeviceProvider of the requested class, or null if none is + * found + */ private static MidiDeviceProvider getNamedProvider(String providerClassName, List providers) { for(int i = 0; i < providers.size(); i++) { @@ -1190,15 +1105,15 @@ public class MidiSystem { return null; } - - /** Return a MidiDevice with a given name from a given MidiDeviceProvider. - @param deviceName The name of the MidiDevice to be returned. - @param provider The MidiDeviceProvider to check for MidiDevices. - @param deviceClass The requested device type, one of Synthesizer.class, - Sequencer.class, Receiver.class or Transmitter.class. - - @return A MidiDevice matching the requirements, or null if none is found. - */ + /** + * Return a MidiDevice with a given name from a given MidiDeviceProvider. + * + * @param deviceName The name of the MidiDevice to be returned + * @param provider The MidiDeviceProvider to check for MidiDevices + * @param deviceClass The requested device type, one of Synthesizer.class, + * Sequencer.class, Receiver.class or Transmitter.class + * @return A MidiDevice matching the requirements, or null if none is found + */ private static MidiDevice getNamedDevice(String deviceName, MidiDeviceProvider provider, Class deviceClass) { @@ -1222,14 +1137,14 @@ public class MidiSystem { return null; } - - /** Return a MidiDevice with a given name from a given MidiDeviceProvider. - @param deviceName The name of the MidiDevice to be returned. - @param provider The MidiDeviceProvider to check for MidiDevices. - @param deviceClass The requested device type, one of Synthesizer.class, - Sequencer.class, Receiver.class or Transmitter.class. - - @return A MidiDevice matching the requirements, or null if none is found. + /** + * Return a MidiDevice with a given name from a given MidiDeviceProvider. + * + * @param deviceName The name of the MidiDevice to be returned + * @param provider The MidiDeviceProvider to check for MidiDevices + * @param deviceClass The requested device type, one of Synthesizer.class, + * Sequencer.class, Receiver.class or Transmitter.class + * @return A MidiDevice matching the requirements, or null if none is found */ private static MidiDevice getNamedDevice(String deviceName, MidiDeviceProvider provider, @@ -1249,16 +1164,16 @@ public class MidiSystem { return null; } - - /** Return a MidiDevice with a given name from a list of - MidiDeviceProviders. - @param deviceName The name of the MidiDevice to be returned. - @param providers The List of MidiDeviceProviders to check for - MidiDevices. - @param deviceClass The requested device type, one of Synthesizer.class, - Sequencer.class, Receiver.class or Transmitter.class. - @return A Mixer matching the requirements, or null if none is found. - */ + /** + * Return a MidiDevice with a given name from a list of MidiDeviceProviders. + * + * @param deviceName The name of the MidiDevice to be returned + * @param providers The List of MidiDeviceProviders to check for + * MidiDevices + * @param deviceClass The requested device type, one of Synthesizer.class, + * Sequencer.class, Receiver.class or Transmitter.class + * @return A Mixer matching the requirements, or null if none is found + */ private static MidiDevice getNamedDevice(String deviceName, List providers, Class deviceClass) { @@ -1282,15 +1197,15 @@ public class MidiSystem { return null; } - - /** Return a MidiDevice with a given name from a list of - MidiDeviceProviders. - @param deviceName The name of the MidiDevice to be returned. - @param providers The List of MidiDeviceProviders to check for - MidiDevices. - @param deviceClass The requested device type, one of Synthesizer.class, - Sequencer.class, Receiver.class or Transmitter.class. - @return A Mixer matching the requirements, or null if none is found. + /** + * Return a MidiDevice with a given name from a list of MidiDeviceProviders. + * + * @param deviceName The name of the MidiDevice to be returned + * @param providers The List of MidiDeviceProviders to check for + * MidiDevices + * @param deviceClass The requested device type, one of Synthesizer.class, + * Sequencer.class, Receiver.class or Transmitter.class + * @return A Mixer matching the requirements, or null if none is found */ private static MidiDevice getNamedDevice(String deviceName, List providers, @@ -1310,14 +1225,15 @@ public class MidiSystem { return null; } - - /** From a given MidiDeviceProvider, return the first appropriate device. - @param provider The MidiDeviceProvider to check for MidiDevices. - @param deviceClass The requested device type, one of Synthesizer.class, - Sequencer.class, Receiver.class or Transmitter.class. - @return A MidiDevice is considered appropriate, or null if no - appropriate device is found. - */ + /** + * From a given MidiDeviceProvider, return the first appropriate device. + * + * @param provider The MidiDeviceProvider to check for MidiDevices + * @param deviceClass The requested device type, one of Synthesizer.class, + * Sequencer.class, Receiver.class or Transmitter.class + * @return A MidiDevice is considered appropriate, or null if no appropriate + * device is found + */ private static MidiDevice getFirstDevice(MidiDeviceProvider provider, Class deviceClass) { MidiDevice device; @@ -1340,13 +1256,14 @@ public class MidiSystem { return null; } - - /** From a given MidiDeviceProvider, return the first appropriate device. - @param provider The MidiDeviceProvider to check for MidiDevices. - @param deviceClass The requested device type, one of Synthesizer.class, - Sequencer.class, Receiver.class or Transmitter.class. - @return A MidiDevice is considered appropriate, or null if no - appropriate device is found. + /** + * From a given MidiDeviceProvider, return the first appropriate device. + * + * @param provider The MidiDeviceProvider to check for MidiDevices + * @param deviceClass The requested device type, one of Synthesizer.class, + * Sequencer.class, Receiver.class or Transmitter.class + * @return A MidiDevice is considered appropriate, or null if no appropriate + * device is found */ private static MidiDevice getFirstDevice(MidiDeviceProvider provider, Class deviceClass, @@ -1363,15 +1280,16 @@ public class MidiSystem { return null; } - - /** From a List of MidiDeviceProviders, return the first appropriate - MidiDevice. - @param providers The List of MidiDeviceProviders to search. - @param deviceClass The requested device type, one of Synthesizer.class, - Sequencer.class, Receiver.class or Transmitter.class. - @return A MidiDevice that is considered appropriate, or null - if none is found. - */ + /** + * From a List of MidiDeviceProviders, return the first appropriate + * MidiDevice. + * + * @param providers The List of MidiDeviceProviders to search + * @param deviceClass The requested device type, one of Synthesizer.class, + * Sequencer.class, Receiver.class or Transmitter.class + * @return A MidiDevice that is considered appropriate, or null if none is + * found + */ private static MidiDevice getFirstDevice(List providers, Class deviceClass) { MidiDevice device; @@ -1394,14 +1312,15 @@ public class MidiSystem { return null; } - - /** From a List of MidiDeviceProviders, return the first appropriate - MidiDevice. - @param providers The List of MidiDeviceProviders to search. - @param deviceClass The requested device type, one of Synthesizer.class, - Sequencer.class, Receiver.class or Transmitter.class. - @return A MidiDevice that is considered appropriate, or null - if none is found. + /** + * From a List of MidiDeviceProviders, return the first appropriate + * MidiDevice. + * + * @param providers The List of MidiDeviceProviders to search + * @param deviceClass The requested device type, one of Synthesizer.class, + * Sequencer.class, Receiver.class or Transmitter.class + * @return A MidiDevice that is considered appropriate, or null if none is + * found */ private static MidiDevice getFirstDevice(List providers, Class deviceClass, @@ -1419,28 +1338,29 @@ public class MidiSystem { return null; } - - /** Checks if a MidiDevice is appropriate. - If deviceClass is Synthesizer or Sequencer, a device implementing - the respective interface is considered appropriate. If deviceClass - is Receiver or Transmitter, a device is considered appropriate if - it implements neither Synthesizer nor Transmitter, and if it can - provide at least one Receiver or Transmitter, respectively. - - @param device the MidiDevice to test - @param allowSynthesizer if true, Synthesizers are considered - appropriate. Otherwise only pure MidiDevices are considered - appropriate (unless allowSequencer is true). This flag only has an - effect for deviceClass Receiver and Transmitter. For other device - classes (Sequencer and Synthesizer), this flag has no effect. - @param allowSequencer if true, Sequencers are considered - appropriate. Otherwise only pure MidiDevices are considered - appropriate (unless allowSynthesizer is true). This flag only has an - effect for deviceClass Receiver and Transmitter. For other device - classes (Sequencer and Synthesizer), this flag has no effect. - @return true if the device is considered appropriate according to the - rules given above, false otherwise. - */ + /** + * Checks if a MidiDevice is appropriate. If deviceClass is Synthesizer or + * Sequencer, a device implementing the respective interface is considered + * appropriate. If deviceClass is Receiver or Transmitter, a device is + * considered appropriate if it implements neither Synthesizer nor + * Transmitter, and if it can provide at least one Receiver or Transmitter, + * respectively. + * + * @param device the MidiDevice to test + * @param allowSynthesizer if true, Synthesizers are considered + * appropriate. Otherwise only pure MidiDevices are considered + * appropriate (unless allowSequencer is true). This flag only has + * an effect for deviceClass Receiver and Transmitter. For other + * device classes (Sequencer and Synthesizer), this flag has no + * effect. + * @param allowSequencer if true, Sequencers are considered appropriate. + * Otherwise only pure MidiDevices are considered appropriate + * (unless allowSynthesizer is true). This flag only has an effect + * for deviceClass Receiver and Transmitter. For other device + * classes (Sequencer and Synthesizer), this flag has no effect. + * @return true if the device is considered appropriate according to the + * rules given above, false otherwise + */ private static boolean isAppropriateDevice(MidiDevice device, Class deviceClass, boolean allowSynthesizer, @@ -1473,12 +1393,12 @@ public class MidiSystem { return false; } - /** - * Obtains the set of services currently installed on the system - * using the SPI mechanism in 1.3. - * @return a List of instances of providers for the requested service. - * If no providers are available, a List of length 0 will be returned. + * Obtains the set of services currently installed on the system using the + * SPI mechanism in 1.3. + * + * @return a List of instances of providers for the requested service. If no + * providers are available, a List of length 0 will be returned. */ private static List getProviders(Class providerClass) { return JDK13Services.getProviders(providerClass); diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiUnavailableException.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiUnavailableException.java index 85ace347d8b..b52fac8d813 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiUnavailableException.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/MidiUnavailableException.java @@ -25,39 +25,37 @@ package javax.sound.midi; - /** - * A MidiUnavailableException is thrown when a requested MIDI - * component cannot be opened or created because it is unavailable. This often - * occurs when a device is in use by another application. More generally, it - * can occur when there is a finite number of a certain kind of resource that can - * be used for some purpose, and all of them are already in use (perhaps all by - * this application). For an example of the latter case, see the + * A {@code MidiUnavailableException} is thrown when a requested MIDI component + * cannot be opened or created because it is unavailable. This often occurs when + * a device is in use by another application. More generally, it can occur when + * there is a finite number of a certain kind of resource that can be used for + * some purpose, and all of them are already in use (perhaps all by this + * application). For an example of the latter case, see the * {@link Transmitter#setReceiver(Receiver) setReceiver} method of - * Transmitter. + * {@code Transmitter}. * * @author Kara Kytle */ public class MidiUnavailableException extends Exception { + private static final long serialVersionUID = 6093809578628944323L; /** - * Constructs a MidiUnavailableException that has - * null as its error detail message. + * Constructs a {@code MidiUnavailableException} that has {@code null} as + * its error detail message. */ public MidiUnavailableException() { - super(); } /** - * Constructs a MidiUnavailableException with the - * specified detail message. + * Constructs a {@code MidiUnavailableException} with the specified detail + * message. * - * @param message the string to display as an error detail message + * @param message the string to display as an error detail message */ - public MidiUnavailableException(String message) { - + public MidiUnavailableException(final String message) { super(message); } } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/Patch.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/Patch.java index d8bc7cf1b4a..f1e438200b9 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/Patch.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/Patch.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2002, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,88 +25,77 @@ package javax.sound.midi; - /** - * A Patch object represents a location, on a MIDI - * synthesizer, into which a single instrument is stored (loaded). - * Every Instrument object has its own Patch - * object that specifies the memory location - * into which that instrument should be loaded. The - * location is specified abstractly by a bank index and a program number (not by - * any scheme that directly refers to a specific address or offset in RAM). - * This is a hierarchical indexing scheme: MIDI provides for up to 16384 banks, - * each of which contains up to 128 program locations. For example, a - * minimal sort of synthesizer might have only one bank of instruments, and - * only 32 instruments (programs) in that bank. + * A {@code Patch} object represents a location, on a MIDI synthesizer, into + * which a single instrument is stored (loaded). Every {@code Instrument} object + * has its own {@code Patch} object that specifies the memory location into + * which that instrument should be loaded. The location is specified abstractly + * by a bank index and a program number (not by any scheme that directly refers + * to a specific address or offset in RAM). This is a hierarchical indexing + * scheme: MIDI provides for up to 16384 banks, each of which contains up to 128 + * program locations. For example, a minimal sort of synthesizer might have only + * one bank of instruments, and only 32 instruments (programs) in that bank. *

    - * To select what instrument should play the notes on a particular MIDI - * channel, two kinds of MIDI message are used that specify a patch location: - * a bank-select command, and a program-change channel command. The Java Sound + * To select what instrument should play the notes on a particular MIDI channel, + * two kinds of MIDI message are used that specify a patch location: a + * bank-select command, and a program-change channel command. The Java Sound * equivalent is the - * {@link MidiChannel#programChange(int, int) programChange(int, int)} - * method of MidiChannel. + * {@link MidiChannel#programChange(int, int) programChange(int, int)} method of + * {@code MidiChannel}. * + * @author Kara Kytle * @see Instrument * @see Instrument#getPatch() * @see MidiChannel#programChange(int, int) * @see Synthesizer#loadInstruments(Soundbank, Patch[]) * @see Soundbank * @see Sequence#getPatchList() - * - * @author Kara Kytle */ - public class Patch { - /** - * Bank index + * Bank index. */ private final int bank; - /** - * Program change number + * Program change number. */ private final int program; - /** * Constructs a new patch object from the specified bank and program * numbers. - * @param bank the bank index (in the range from 0 to 16383) - * @param program the program index (in the range from 0 to 127) + * + * @param bank the bank index (in the range from 0 to 16383) + * @param program the program index (in the range from 0 to 127) */ public Patch(int bank, int program) { - this.bank = bank; this.program = program; } - /** - * Returns the number of the bank that contains the instrument - * whose location this Patch specifies. + * Returns the number of the bank that contains the instrument whose + * location this {@code Patch} specifies. + * * @return the bank number, whose range is from 0 to 16383 * @see MidiChannel#programChange(int, int) */ public int getBank() { - return bank; } - /** - * Returns the index, within - * a bank, of the instrument whose location this Patch specifies. - * @return the instrument's program number, whose range is from 0 to 127 + * Returns the index, within a bank, of the instrument whose location this + * {@code Patch} specifies. * + * @return the instrument's program number, whose range is from 0 to 127 * @see MidiChannel#getProgram * @see MidiChannel#programChange(int) * @see MidiChannel#programChange(int, int) */ public int getProgram() { - return program; } } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/Receiver.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/Receiver.java index 9df0a5d7153..55e038cfa86 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/Receiver.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/Receiver.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,50 +25,46 @@ package javax.sound.midi; - /** - * A Receiver receives {@link MidiEvent} objects and - * typically does something useful in response, such as interpreting them to - * generate sound or raw MIDI output. Common MIDI receivers include - * synthesizers and MIDI Out ports. + * A {@code Receiver} receives {@link MidiEvent} objects and typically does + * something useful in response, such as interpreting them to generate sound or + * raw MIDI output. Common MIDI receivers include synthesizers and MIDI Out + * ports. * + * @author Kara Kytle * @see MidiDevice * @see Synthesizer * @see Transmitter - * - * @author Kara Kytle */ public interface Receiver extends AutoCloseable { - //$$fb 2002-04-12: fix for 4662090: Contradiction in Receiver specification + /** - * Sends a MIDI message and time-stamp to this receiver. - * If time-stamping is not supported by this receiver, the time-stamp - * value should be -1. - * @param message the MIDI message to send - * @param timeStamp the time-stamp for the message, in microseconds. + * Sends a MIDI message and time-stamp to this receiver. If time-stamping is + * not supported by this receiver, the time-stamp value should be -1. + * + * @param message the MIDI message to send + * @param timeStamp the time-stamp for the message, in microseconds * @throws IllegalStateException if the receiver is closed */ - public void send(MidiMessage message, long timeStamp); + void send(MidiMessage message, long timeStamp); /** - * Indicates that the application has finished using the receiver, and - * that limited resources it requires may be released or made available. - * - *

    If the creation of this Receiver resulted in - * implicitly opening the underlying device, the device is - * implicitly closed by this method. This is true unless the device is - * kept open by other Receiver or Transmitter - * instances that opened the device implicitly, and unless the device - * has been opened explicitly. If the device this - * Receiver is retrieved from is closed explicitly by - * calling {@link MidiDevice#close MidiDevice.close}, the - * Receiver is closed, too. For a detailed - * description of open/close behaviour see the class description - * of {@link javax.sound.midi.MidiDevice MidiDevice}. + * Indicates that the application has finished using the receiver, and that + * limited resources it requires may be released or made available. + *

    + * If the creation of this {@code Receiver} resulted in implicitly opening + * the underlying device, the device is implicitly closed by this method. + * This is true unless the device is kept open by other {@code Receiver} or + * {@code Transmitter} instances that opened the device implicitly, and + * unless the device has been opened explicitly. If the device this + * {@code Receiver} is retrieved from is closed explicitly by calling + * {@link MidiDevice#close MidiDevice.close}, the {@code Receiver} is + * closed, too. For a detailed description of open/close behaviour see the + * class description of {@link MidiDevice MidiDevice}. * * @see javax.sound.midi.MidiSystem#getReceiver */ - public void close(); + void close(); } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/Sequence.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/Sequence.java index 14cb66110ed..3dd0ca5801c 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/Sequence.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/Sequence.java @@ -26,72 +26,77 @@ package javax.sound.midi; import java.util.Vector; -import com.sun.media.sound.MidiUtils; - /** - * A Sequence is a data structure containing musical - * information (often an entire song or composition) that can be played - * back by a {@link Sequencer} object. Specifically, the - * Sequence contains timing - * information and one or more tracks. Each {@link Track track} consists of a - * series of MIDI events (such as note-ons, note-offs, program changes, and meta-events). - * The sequence's timing information specifies the type of unit that is used - * to time-stamp the events in the sequence. + * A {@code Sequence} is a data structure containing musical information (often + * an entire song or composition) that can be played back by a {@link Sequencer} + * object. Specifically, the {@code Sequence} contains timing information and + * one or more tracks. Each {@link Track track} consists of a series of MIDI + * events (such as note-ons, note-offs, program changes, and meta-events). The + * sequence's timing information specifies the type of unit that is used to + * time-stamp the events in the sequence. *

    - * A Sequence can be created from a MIDI file by reading the file - * into an input stream and invoking one of the getSequence methods of - * {@link MidiSystem}. A sequence can also be built from scratch by adding new - * Tracks to an empty Sequence, and adding - * {@link MidiEvent} objects to these Tracks. + * A {@code Sequence} can be created from a MIDI file by reading the file into + * an input stream and invoking one of the {@code getSequence} methods of + * {@link MidiSystem}. A sequence can also be built from scratch by adding new + * {@code Tracks} to an empty {@code Sequence}, and adding {@link MidiEvent} + * objects to these {@code Tracks}. * + * @author Kara Kytle * @see Sequencer#setSequence(java.io.InputStream stream) * @see Sequencer#setSequence(Sequence sequence) * @see Track#add(MidiEvent) * @see MidiFileFormat - * - * @author Kara Kytle */ public class Sequence { - // Timing types /** - * The tempo-based timing type, for which the resolution is expressed in pulses (ticks) per quarter note. + * The tempo-based timing type, for which the resolution is expressed in + * pulses (ticks) per quarter note. + * * @see #Sequence(float, int) */ public static final float PPQ = 0.0f; /** - * The SMPTE-based timing type with 24 frames per second (resolution is expressed in ticks per frame). + * The SMPTE-based timing type with 24 frames per second (resolution is + * expressed in ticks per frame). + * * @see #Sequence(float, int) */ public static final float SMPTE_24 = 24.0f; /** - * The SMPTE-based timing type with 25 frames per second (resolution is expressed in ticks per frame). + * The SMPTE-based timing type with 25 frames per second (resolution is + * expressed in ticks per frame). + * * @see #Sequence(float, int) */ public static final float SMPTE_25 = 25.0f; /** - * The SMPTE-based timing type with 29.97 frames per second (resolution is expressed in ticks per frame). + * The SMPTE-based timing type with 29.97 frames per second (resolution is + * expressed in ticks per frame). + * * @see #Sequence(float, int) */ public static final float SMPTE_30DROP = 29.97f; /** - * The SMPTE-based timing type with 30 frames per second (resolution is expressed in ticks per frame). + * The SMPTE-based timing type with 30 frames per second (resolution is + * expressed in ticks per frame). + * * @see #Sequence(float, int) */ public static final float SMPTE_30 = 30.0f; - // Variables /** * The timing division type of the sequence. + * * @see #PPQ * @see #SMPTE_24 * @see #SMPTE_25 @@ -103,33 +108,33 @@ public class Sequence { /** * The timing resolution of the sequence. + * * @see #getResolution */ protected int resolution; /** * The MIDI tracks in this sequence. + * * @see #getTracks */ protected Vector tracks = new Vector(); - /** - * Constructs a new MIDI sequence with the specified timing division - * type and timing resolution. The division type must be one of the - * recognized MIDI timing types. For tempo-based timing, - * divisionType is PPQ (pulses per quarter note) and - * the resolution is specified in ticks per beat. For SMTPE timing, - * divisionType specifies the number of frames per - * second and the resolution is specified in ticks per frame. - * The sequence will contain no initial tracks. Tracks may be - * added to or removed from the sequence using {@link #createTrack} - * and {@link #deleteTrack}. - * - * @param divisionType the timing division type (PPQ or one of the SMPTE types) - * @param resolution the timing resolution - * @throws InvalidMidiDataException if divisionType is not valid + * Constructs a new MIDI sequence with the specified timing division type + * and timing resolution. The division type must be one of the recognized + * MIDI timing types. For tempo-based timing, {@code divisionType} is PPQ + * (pulses per quarter note) and the resolution is specified in ticks per + * beat. For SMTPE timing, {@code divisionType} specifies the number of + * frames per second and the resolution is specified in ticks per frame. The + * sequence will contain no initial tracks. Tracks may be added to or + * removed from the sequence using {@link #createTrack} and + * {@link #deleteTrack}. * + * @param divisionType the timing division type (PPQ or one of the SMPTE + * types) + * @param resolution the timing resolution + * @throws InvalidMidiDataException if {@code divisionType} is not valid * @see #PPQ * @see #SMPTE_24 * @see #SMPTE_25 @@ -156,27 +161,25 @@ public class Sequence { this.resolution = resolution; } - /** - * Constructs a new MIDI sequence with the specified timing division - * type, timing resolution, and number of tracks. The division type must be one of the - * recognized MIDI timing types. For tempo-based timing, - * divisionType is PPQ (pulses per quarter note) and - * the resolution is specified in ticks per beat. For SMTPE timing, - * divisionType specifies the number of frames per - * second and the resolution is specified in ticks per frame. - * The sequence will be initialized with the number of tracks specified by - * numTracks. These tracks are initially empty (i.e. - * they contain only the meta-event End of Track). - * The tracks may be retrieved for editing using the {@link #getTracks} - * method. Additional tracks may be added, or existing tracks removed, - * using {@link #createTrack} and {@link #deleteTrack}. - * - * @param divisionType the timing division type (PPQ or one of the SMPTE types) - * @param resolution the timing resolution - * @param numTracks the initial number of tracks in the sequence. - * @throws InvalidMidiDataException if divisionType is not valid + * Constructs a new MIDI sequence with the specified timing division type, + * timing resolution, and number of tracks. The division type must be one of + * the recognized MIDI timing types. For tempo-based timing, + * {@code divisionType} is PPQ (pulses per quarter note) and the resolution + * is specified in ticks per beat. For SMTPE timing, {@code divisionType} + * specifies the number of frames per second and the resolution is specified + * in ticks per frame. The sequence will be initialized with the number of + * tracks specified by {@code numTracks}. These tracks are initially empty + * (i.e. they contain only the meta-event End of Track). The tracks may be + * retrieved for editing using the {@link #getTracks} method. Additional + * tracks may be added, or existing tracks removed, using + * {@link #createTrack} and {@link #deleteTrack}. * + * @param divisionType the timing division type (PPQ or one of the SMPTE + * types) + * @param resolution the timing resolution + * @param numTracks the initial number of tracks in the sequence + * @throws InvalidMidiDataException if {@code divisionType} is not valid * @see #PPQ * @see #SMPTE_24 * @see #SMPTE_25 @@ -206,11 +209,10 @@ public class Sequence { } } - /** * Obtains the timing division type for this sequence. - * @return the division type (PPQ or one of the SMPTE types) * + * @return the division type (PPQ or one of the SMPTE types) * @see #PPQ * @see #SMPTE_24 * @see #SMPTE_25 @@ -223,11 +225,10 @@ public class Sequence { return divisionType; } - /** - * Obtains the timing resolution for this sequence. - * If the sequence's division type is PPQ, the resolution is specified in ticks per beat. - * For SMTPE timing, the resolution is specified in ticks per frame. + * Obtains the timing resolution for this sequence. If the sequence's + * division type is PPQ, the resolution is specified in ticks per beat. For + * SMTPE timing, the resolution is specified in ticks per frame. * * @return the number of ticks per beat (PPQ) or per frame (SMPTE) * @see #getDivisionType @@ -238,13 +239,13 @@ public class Sequence { return resolution; } - /** - * Creates a new, initially empty track as part of this sequence. - * The track initially contains the meta-event End of Track. - * The newly created track is returned. All tracks in the sequence - * may be retrieved using {@link #getTracks}. Tracks may be - * removed from the sequence using {@link #deleteTrack}. + * Creates a new, initially empty track as part of this sequence. The track + * initially contains the meta-event End of Track. The newly created track + * is returned. All tracks in the sequence may be retrieved using + * {@link #getTracks}. Tracks may be removed from the sequence using + * {@link #deleteTrack}. + * * @return the newly created track */ public Track createTrack() { @@ -255,13 +256,12 @@ public class Sequence { return track; } - /** * Removes the specified track from the sequence. - * @param track the track to remove - * @return true if the track existed in the track and was removed, - * otherwise false. * + * @param track the track to remove + * @return {@code true} if the track existed in the track and was removed, + * otherwise {@code false} * @see #createTrack * @see #getTracks */ @@ -273,12 +273,11 @@ public class Sequence { } } - /** - * Obtains an array containing all the tracks in this sequence. - * If the sequence contains no tracks, an array of length 0 is returned. - * @return the array of tracks + * Obtains an array containing all the tracks in this sequence. If the + * sequence contains no tracks, an array of length 0 is returned. * + * @return the array of tracks * @see #createTrack * @see #deleteTrack */ @@ -287,22 +286,20 @@ public class Sequence { return tracks.toArray(new Track[tracks.size()]); } - /** * Obtains the duration of this sequence, expressed in microseconds. - * @return this sequence's duration in microseconds. + * + * @return this sequence's duration in microseconds */ public long getMicrosecondLength() { return com.sun.media.sound.MidiUtils.tick2microsecond(this, getTickLength(), null); } - /** * Obtains the duration of this sequence, expressed in MIDI ticks. * * @return this sequence's length in ticks - * * @see #getMicrosecondLength */ public long getTickLength() { @@ -321,15 +318,12 @@ public class Sequence { } } - /** - * Obtains a list of patches referenced in this sequence. - * This patch list may be used to load the required - * {@link Instrument} objects - * into a {@link Synthesizer}. - * - * @return an array of {@link Patch} objects used in this sequence + * Obtains a list of patches referenced in this sequence. This patch list + * may be used to load the required {@link Instrument} objects into a + * {@link Synthesizer}. * + * @return an array of {@link Patch} objects used in this sequence * @see Synthesizer#loadInstruments(Soundbank, Patch[]) */ public Patch[] getPatchList() { diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/Sequencer.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/Sequencer.java index b587d29b544..17d6a9dc197 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/Sequencer.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/Sequencer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,19 +25,18 @@ package javax.sound.midi; -import java.io.InputStream; import java.io.IOException; - +import java.io.InputStream; /** * A hardware or software device that plays back a MIDI - * {@link Sequence sequence} is known as a sequencer. - * A MIDI sequence contains lists of time-stamped MIDI data, such as - * might be read from a standard MIDI file. Most - * sequencers also provide functions for creating and editing sequences. + * {@link Sequence sequence} is known as a sequencer. A MIDI sequence + * contains lists of time-stamped MIDI data, such as might be read from a + * standard MIDI file. Most sequencers also provide functions for creating and + * editing sequences. *

    - * The Sequencer interface includes methods for the following - * basic MIDI sequencer operations: + * The {@code Sequencer} interface includes methods for the following basic MIDI + * sequencer operations: *

      *
    • obtaining a sequence from MIDI file data
    • *
    • starting and stopping playback
    • @@ -48,729 +47,635 @@ import java.io.IOException; *
    • controlling the timing of another device
    • *
    * In addition, the following operations are supported, either directly, or - * indirectly through objects that the Sequencer has access to: + * indirectly through objects that the {@code Sequencer} has access to: *
      *
    • editing the data by adding or deleting individual MIDI events or entire * tracks
    • *
    • muting or soloing individual tracks in the sequence
    • - *
    • notifying listener objects about any meta-events or - * control-change events encountered while playing back the sequence.
    • + *
    • notifying listener objects about any meta-events or control-change events + * encountered while playing back the sequence.
    • *
    * - * @see Sequencer.SyncMode + * @author Kara Kytle + * @author Florian Bomers + * @see SyncMode * @see #addMetaEventListener * @see ControllerEventListener * @see Receiver * @see Transmitter * @see MidiDevice - * - * @author Kara Kytle - * @author Florian Bomers */ public interface Sequencer extends MidiDevice { - /** - * A value indicating that looping should continue - * indefinitely rather than complete after a specific - * number of loops. + * A value indicating that looping should continue indefinitely rather than + * complete after a specific number of loops. * * @see #setLoopCount * @since 1.5 */ - public static final int LOOP_CONTINUOUSLY = -1; - - + int LOOP_CONTINUOUSLY = -1; /** * Sets the current sequence on which the sequencer operates. + *

    + * This method can be called even if the {@code Sequencer} is closed. * - *

    This method can be called even if the - * Sequencer is closed. - * - * @param sequence the sequence to be loaded. - * @throws InvalidMidiDataException if the sequence contains invalid - * MIDI data, or is not supported. + * @param sequence the sequence to be loaded + * @throws InvalidMidiDataException if the sequence contains invalid MIDI + * data, or is not supported */ - public void setSequence(Sequence sequence) throws InvalidMidiDataException; - + void setSequence(Sequence sequence) throws InvalidMidiDataException; /** - * Sets the current sequence on which the sequencer operates. - * The stream must point to MIDI file data. + * Sets the current sequence on which the sequencer operates. The stream + * must point to MIDI file data. + *

    + * This method can be called even if the {@code Sequencer} is closed. * - *

    This method can be called even if the - * Sequencer is closed. - * - * @param stream stream containing MIDI file data. - * @throws IOException if an I/O exception occurs during reading of the stream. - * @throws InvalidMidiDataException if invalid data is encountered - * in the stream, or the stream is not supported. + * @param stream stream containing MIDI file data + * @throws IOException if an I/O exception occurs during reading of the + * stream + * @throws InvalidMidiDataException if invalid data is encountered in the + * stream, or the stream is not supported */ - public void setSequence(InputStream stream) throws IOException, InvalidMidiDataException; - + void setSequence(InputStream stream) + throws IOException, InvalidMidiDataException; /** * Obtains the sequence on which the Sequencer is currently operating. + *

    + * This method can be called even if the {@code Sequencer} is closed. * - *

    This method can be called even if the - * Sequencer is closed. - * - * @return the current sequence, or null if no sequence is currently set. + * @return the current sequence, or {@code null} if no sequence is currently + * set */ - public Sequence getSequence(); - + Sequence getSequence(); /** - * Starts playback of the MIDI data in the currently - * loaded sequence. - * Playback will begin from the current position. - * If the playback position reaches the loop end point, - * and the loop count is greater than 0, playback will - * resume at the loop start point for the number of - * repetitions set with setLoopCount. - * After that, or if the loop count is 0, playback will - * continue to play to the end of the sequence. - * - *

    The implementation ensures that the synthesizer - * is brought to a consistent state when jumping - * to the loop start point by sending appropriate - * controllers, pitch bend, and program change events. - * - * @throws IllegalStateException if the Sequencer is - * closed. + * Starts playback of the MIDI data in the currently loaded sequence. + * Playback will begin from the current position. If the playback position + * reaches the loop end point, and the loop count is greater than 0, + * playback will resume at the loop start point for the number of + * repetitions set with {@code setLoopCount}. After that, or if the loop + * count is 0, playback will continue to play to the end of the sequence. + *

    + * The implementation ensures that the synthesizer is brought to a + * consistent state when jumping to the loop start point by sending + * appropriate controllers, pitch bend, and program change events. * + * @throws IllegalStateException if the {@code Sequencer} is closed * @see #setLoopStartPoint * @see #setLoopEndPoint * @see #setLoopCount * @see #stop */ - public void start(); - + void start(); /** - * Stops recording, if active, and playback of the currently loaded sequence, - * if any. - * - * @throws IllegalStateException if the Sequencer is - * closed. + * Stops recording, if active, and playback of the currently loaded + * sequence, if any. * + * @throws IllegalStateException if the {@code Sequencer} is closed * @see #start * @see #isRunning */ - public void stop(); - + void stop(); /** - * Indicates whether the Sequencer is currently running. The default is false. - * The Sequencer starts running when either {@link #start} or {@link #startRecording} - * is called. isRunning then returns true until playback of the - * sequence completes or {@link #stop} is called. - * @return true if the Sequencer is running, otherwise false + * Indicates whether the Sequencer is currently running. The default is + * {@code false}. The Sequencer starts running when either{@link #start} or + * {@link #startRecording} is called. {@code isRunning} then returns + * {@code true} until playback of the sequence completes or {@link #stop} is + * called. + * + * @return {@code true} if the Sequencer is running, otherwise {@code false} */ - public boolean isRunning(); - + boolean isRunning(); /** - * Starts recording and playback of MIDI data. Data is recorded to all enabled tracks, - * on the channel(s) for which they were enabled. Recording begins at the current position - * of the sequencer. Any events already in the track are overwritten for the duration - * of the recording session. Events from the currently loaded sequence, - * if any, are delivered to the sequencer's transmitter(s) along with messages - * received during recording. + * Starts recording and playback of MIDI data. Data is recorded to all + * enabled tracks, on the channel(s) for which they were enabled. Recording + * begins at the current position of the sequencer. Any events already in + * the track are overwritten for the duration of the recording session. + * Events from the currently loaded sequence, if any, are delivered to the + * sequencer's transmitter(s) along with messages received during recording. *

    - * Note that tracks are not by default enabled for recording. In order to record MIDI data, - * at least one track must be specifically enabled for recording. + * Note that tracks are not by default enabled for recording. In order to + * record MIDI data, at least one track must be specifically enabled for + * recording. * - * @throws IllegalStateException if the Sequencer is - * closed. - * - * @see #startRecording + * @throws IllegalStateException if the {@code Sequencer} is closed * @see #recordEnable * @see #recordDisable */ - public void startRecording(); - + void startRecording(); /** - * Stops recording, if active. Playback of the current sequence continues. - * - * @throws IllegalStateException if the Sequencer is - * closed. + * Stops recording, if active. Playback of the current sequence continues. * + * @throws IllegalStateException if the {@code Sequencer} is closed * @see #startRecording * @see #isRecording */ - public void stopRecording(); - + void stopRecording(); /** - * Indicates whether the Sequencer is currently recording. The default is false. - * The Sequencer begins recording when {@link #startRecording} is called, - * and then returns true until {@link #stop} or {@link #stopRecording} - * is called. - * @return true if the Sequencer is recording, otherwise false + * Indicates whether the Sequencer is currently recording. The default is + * {@code false}. The Sequencer begins recording when + * {@link #startRecording} is called, and then returns {@code true} until + * {@link #stop} or {@link #stopRecording} is called. + * + * @return {@code true} if the Sequencer is recording, otherwise + * {@code false} */ - public boolean isRecording(); - + boolean isRecording(); /** - * Prepares the specified track for recording events received on a particular channel. - * Once enabled, a track will receive events when recording is active. - * @param track the track to which events will be recorded - * @param channel the channel on which events will be received. If -1 is specified - * for the channel value, the track will receive data from all channels. - * @throws IllegalArgumentException thrown if the track is not part of the current - * sequence. + * Prepares the specified track for recording events received on a + * particular channel. Once enabled, a track will receive events when + * recording is active. + * + * @param track the track to which events will be recorded + * @param channel the channel on which events will be received. If -1 is + * specified for the channel value, the track will receive data from + * all channels. + * @throws IllegalArgumentException thrown if the track is not part of the + * current sequence */ - public void recordEnable(Track track, int channel); - + void recordEnable(Track track, int channel); /** - * Disables recording to the specified track. Events will no longer be recorded - * into this track. - * @param track the track to disable for recording, or null to disable - * recording for all tracks. + * Disables recording to the specified track. Events will no longer be + * recorded into this track. + * + * @param track the track to disable for recording, or {@code null} to + * disable recording for all tracks */ - public void recordDisable(Track track); - + void recordDisable(Track track); /** - * Obtains the current tempo, expressed in beats per minute. The - * actual tempo of playback is the product of the returned value - * and the tempo factor. + * Obtains the current tempo, expressed in beats per minute. The actual + * tempo of playback is the product of the returned value and the tempo + * factor. * * @return the current tempo in beats per minute - * * @see #getTempoFactor * @see #setTempoInBPM(float) * @see #getTempoInMPQ */ - public float getTempoInBPM(); - + float getTempoInBPM(); /** - * Sets the tempo in beats per minute. The actual tempo of playback - * is the product of the specified value and the tempo factor. + * Sets the tempo in beats per minute. The actual tempo of playback is the + * product of the specified value and the tempo factor. * - * @param bpm desired new tempo in beats per minute + * @param bpm desired new tempo in beats per minute * @see #getTempoFactor * @see #setTempoInMPQ(float) * @see #getTempoInBPM */ - public void setTempoInBPM(float bpm); - + void setTempoInBPM(float bpm); /** - * Obtains the current tempo, expressed in microseconds per quarter - * note. The actual tempo of playback is the product of the returned - * value and the tempo factor. + * Obtains the current tempo, expressed in microseconds per quarter note. + * The actual tempo of playback is the product of the returned value and the + * tempo factor. * * @return the current tempo in microseconds per quarter note * @see #getTempoFactor * @see #setTempoInMPQ(float) * @see #getTempoInBPM */ - public float getTempoInMPQ(); - + float getTempoInMPQ(); /** - * Sets the tempo in microseconds per quarter note. The actual tempo - * of playback is the product of the specified value and the tempo - * factor. + * Sets the tempo in microseconds per quarter note. The actual tempo of + * playback is the product of the specified value and the tempo factor. * - * @param mpq desired new tempo in microseconds per quarter note. + * @param mpq desired new tempo in microseconds per quarter note * @see #getTempoFactor * @see #setTempoInBPM(float) * @see #getTempoInMPQ */ - public void setTempoInMPQ(float mpq); - + void setTempoInMPQ(float mpq); /** - * Scales the sequencer's actual playback tempo by the factor provided. - * The default is 1.0. A value of 1.0 represents the natural rate (the - * tempo specified in the sequence), 2.0 means twice as fast, etc. - * The tempo factor does not affect the values returned by - * {@link #getTempoInMPQ} and {@link #getTempoInBPM}. - * Those values indicate the tempo prior to scaling. + * Scales the sequencer's actual playback tempo by the factor provided. The + * default is 1.0. A value of 1.0 represents the natural rate (the tempo + * specified in the sequence), 2.0 means twice as fast, etc. The tempo + * factor does not affect the values returned by {@link #getTempoInMPQ} and + * {@link #getTempoInBPM}. Those values indicate the tempo prior to scaling. *

    * Note that the tempo factor cannot be adjusted when external - * synchronization is used. In that situation, - * setTempoFactor always sets the tempo factor to 1.0. + * synchronization is used. In that situation, {@code setTempoFactor} always + * sets the tempo factor to 1.0. * - * @param factor the requested tempo scalar + * @param factor the requested tempo scalar * @see #getTempoFactor */ - public void setTempoFactor(float factor); - + void setTempoFactor(float factor); /** - * Returns the current tempo factor for the sequencer. The default is - * 1.0. + * Returns the current tempo factor for the sequencer. The default is 1.0. * - * @return tempo factor. + * @return tempo factor * @see #setTempoFactor(float) */ - public float getTempoFactor(); - + float getTempoFactor(); /** - * Obtains the length of the current sequence, expressed in MIDI ticks, - * or 0 if no sequence is set. + * Obtains the length of the current sequence, expressed in MIDI ticks, or 0 + * if no sequence is set. + * * @return length of the sequence in ticks */ - public long getTickLength(); - + long getTickLength(); /** - * Obtains the current position in the sequence, expressed in MIDI - * ticks. (The duration of a tick in seconds is determined both by - * the tempo and by the timing resolution stored in the - * {@link Sequence}.) + * Obtains the current position in the sequence, expressed in MIDI ticks. + * (The duration of a tick in seconds is determined both by the tempo and by + * the timing resolution stored in the {@link Sequence}.) * * @return current tick * @see #setTickPosition */ - public long getTickPosition(); - + long getTickPosition(); /** - * Sets the current sequencer position in MIDI ticks - * @param tick the desired tick position + * Sets the current sequencer position in MIDI ticks. + * + * @param tick the desired tick position * @see #getTickPosition */ - public void setTickPosition(long tick); - + void setTickPosition(long tick); /** - * Obtains the length of the current sequence, expressed in microseconds, - * or 0 if no sequence is set. - * @return length of the sequence in microseconds. + * Obtains the length of the current sequence, expressed in microseconds, or + * 0 if no sequence is set. + * + * @return length of the sequence in microseconds */ - public long getMicrosecondLength(); - + long getMicrosecondLength(); /** - * Obtains the current position in the sequence, expressed in - * microseconds. + * Obtains the current position in the sequence, expressed in microseconds. + * * @return the current position in microseconds * @see #setMicrosecondPosition */ - public long getMicrosecondPosition(); - + long getMicrosecondPosition(); /** - * Sets the current position in the sequence, expressed in microseconds - * @param microseconds desired position in microseconds + * Sets the current position in the sequence, expressed in microseconds. + * + * @param microseconds desired position in microseconds * @see #getMicrosecondPosition */ - public void setMicrosecondPosition(long microseconds); - + void setMicrosecondPosition(long microseconds); /** - * Sets the source of timing information used by this sequencer. - * The sequencer synchronizes to the master, which is the internal clock, - * MIDI clock, or MIDI time code, depending on the value of - * sync. The sync argument must be one - * of the supported modes, as returned by - * {@link #getMasterSyncModes}. - * - * @param sync the desired master synchronization mode + * Sets the source of timing information used by this sequencer. The + * sequencer synchronizes to the master, which is the internal clock, MIDI + * clock, or MIDI time code, depending on the value of {@code sync}. The + * {@code sync} argument must be one of the supported modes, as returned by + * {@link #getMasterSyncModes}. * + * @param sync the desired master synchronization mode * @see SyncMode#INTERNAL_CLOCK * @see SyncMode#MIDI_SYNC * @see SyncMode#MIDI_TIME_CODE * @see #getMasterSyncMode */ - public void setMasterSyncMode(SyncMode sync); - + void setMasterSyncMode(SyncMode sync); /** * Obtains the current master synchronization mode for this sequencer. * * @return the current master synchronization mode - * - * @see #setMasterSyncMode(Sequencer.SyncMode) + * @see #setMasterSyncMode(SyncMode) * @see #getMasterSyncModes */ - public SyncMode getMasterSyncMode(); - + SyncMode getMasterSyncMode(); /** * Obtains the set of master synchronization modes supported by this * sequencer. * * @return the available master synchronization modes - * * @see SyncMode#INTERNAL_CLOCK * @see SyncMode#MIDI_SYNC * @see SyncMode#MIDI_TIME_CODE * @see #getMasterSyncMode - * @see #setMasterSyncMode(Sequencer.SyncMode) + * @see #setMasterSyncMode(SyncMode) */ - public SyncMode[] getMasterSyncModes(); - + SyncMode[] getMasterSyncModes(); /** - * Sets the slave synchronization mode for the sequencer. - * This indicates the type of timing information sent by the sequencer - * to its receiver. The sync argument must be one - * of the supported modes, as returned by - * {@link #getSlaveSyncModes}. - * - * @param sync the desired slave synchronization mode + * Sets the slave synchronization mode for the sequencer. This indicates the + * type of timing information sent by the sequencer to its receiver. The + * {@code sync} argument must be one of the supported modes, as returned by + * {@link #getSlaveSyncModes}. * + * @param sync the desired slave synchronization mode * @see SyncMode#MIDI_SYNC * @see SyncMode#MIDI_TIME_CODE * @see SyncMode#NO_SYNC * @see #getSlaveSyncModes */ - public void setSlaveSyncMode(SyncMode sync); - + void setSlaveSyncMode(SyncMode sync); /** * Obtains the current slave synchronization mode for this sequencer. * * @return the current slave synchronization mode - * - * @see #setSlaveSyncMode(Sequencer.SyncMode) + * @see #setSlaveSyncMode(SyncMode) * @see #getSlaveSyncModes */ - public SyncMode getSlaveSyncMode(); - + SyncMode getSlaveSyncMode(); /** - * Obtains the set of slave synchronization modes supported by the sequencer. + * Obtains the set of slave synchronization modes supported by the + * sequencer. * * @return the available slave synchronization modes - * * @see SyncMode#MIDI_SYNC * @see SyncMode#MIDI_TIME_CODE * @see SyncMode#NO_SYNC */ - public SyncMode[] getSlaveSyncModes(); - + SyncMode[] getSlaveSyncModes(); /** - * Sets the mute state for a track. This method may fail for a number - * of reasons. For example, the track number specified may not be valid - * for the current sequence, or the sequencer may not support this functionality. - * An application which needs to verify whether this operation succeeded should - * follow this call with a call to {@link #getTrackMute}. + * Sets the mute state for a track. This method may fail for a number of + * reasons. For example, the track number specified may not be valid for the + * current sequence, or the sequencer may not support this functionality. An + * application which needs to verify whether this operation succeeded should + * follow this call with a call to {@link #getTrackMute}. * - * @param track the track number. Tracks in the current sequence are numbered - * from 0 to the number of tracks in the sequence minus 1. - * @param mute the new mute state for the track. true implies the - * track should be muted, false implies the track should be unmuted. + * @param track the track number. Tracks in the current sequence are + * numbered from 0 to the number of tracks in the sequence minus 1. + * @param mute the new mute state for the track. {@code true} implies the + * track should be muted, {@code false} implies the track should be + * unmuted. * @see #getSequence */ - public void setTrackMute(int track, boolean mute); - + void setTrackMute(int track, boolean mute); /** - * Obtains the current mute state for a track. The default mute - * state for all tracks which have not been muted is false. In any - * case where the specified track has not been muted, this method should - * return false. This applies if the sequencer does not support muting - * of tracks, and if the specified track index is not valid. + * Obtains the current mute state for a track. The default mute state for + * all tracks which have not been muted is false. In any case where the + * specified track has not been muted, this method should return false. This + * applies if the sequencer does not support muting of tracks, and if the + * specified track index is not valid. * - * @param track the track number. Tracks in the current sequence are numbered - * from 0 to the number of tracks in the sequence minus 1. - * @return true if muted, false if not. + * @param track the track number. Tracks in the current sequence are + * numbered from 0 to the number of tracks in the sequence minus 1. + * @return {@code true} if muted, {@code false} if not */ - public boolean getTrackMute(int track); + boolean getTrackMute(int track); /** - * Sets the solo state for a track. If solo is true - * only this track and other solo'd tracks will sound. If solo - * is false then only other solo'd tracks will sound, unless no - * tracks are solo'd in which case all un-muted tracks will sound. + * Sets the solo state for a track. If {@code solo} is {@code true} only + * this track and other solo'd tracks will sound. If {@code solo} is + * {@code false} then only other solo'd tracks will sound, unless no tracks + * are solo'd in which case all un-muted tracks will sound. *

    - * This method may fail for a number - * of reasons. For example, the track number specified may not be valid - * for the current sequence, or the sequencer may not support this functionality. - * An application which needs to verify whether this operation succeeded should - * follow this call with a call to {@link #getTrackSolo}. + * This method may fail for a number of reasons. For example, the track + * number specified may not be valid for the current sequence, or the + * sequencer may not support this functionality. An application which needs + * to verify whether this operation succeeded should follow this call with a + * call to {@link #getTrackSolo}. * - * @param track the track number. Tracks in the current sequence are numbered - * from 0 to the number of tracks in the sequence minus 1. - * @param solo the new solo state for the track. true implies the - * track should be solo'd, false implies the track should not be solo'd. + * @param track the track number. Tracks in the current sequence are + * numbered from 0 to the number of tracks in the sequence minus 1. + * @param solo the new solo state for the track. {@code true} implies the + * track should be solo'd, {@code false} implies the track should + * not be solo'd. * @see #getSequence */ - public void setTrackSolo(int track, boolean solo); - + void setTrackSolo(int track, boolean solo); /** - * Obtains the current solo state for a track. The default mute - * state for all tracks which have not been solo'd is false. In any - * case where the specified track has not been solo'd, this method should - * return false. This applies if the sequencer does not support soloing - * of tracks, and if the specified track index is not valid. + * Obtains the current solo state for a track. The default mute state for + * all tracks which have not been solo'd is false. In any case where the + * specified track has not been solo'd, this method should return false. + * This applies if the sequencer does not support soloing of tracks, and if + * the specified track index is not valid. * - * @param track the track number. Tracks in the current sequence are numbered - * from 0 to the number of tracks in the sequence minus 1. - * @return true if solo'd, false if not. + * @param track the track number. Tracks in the current sequence are + * numbered from 0 to the number of tracks in the sequence minus 1. + * @return {@code true} if solo'd, {@code false} if not */ - public boolean getTrackSolo(int track); - + boolean getTrackSolo(int track); /** - * Registers a meta-event listener to receive - * notification whenever a meta-event is encountered in the sequence - * and processed by the sequencer. This method can fail if, for - * instance,this class of sequencer does not support meta-event - * notification. - * - * @param listener listener to add - * @return true if the listener was successfully added, - * otherwise false + * Registers a meta-event listener to receive notification whenever a + * meta-event is encountered in the sequence and processed by the sequencer. + * This method can fail if, for instance,this class of sequencer does not + * support meta-event notification. * + * @param listener listener to add + * @return {@code true} if the listener was successfully added, otherwise + * {@code false} * @see #removeMetaEventListener * @see MetaEventListener * @see MetaMessage */ - public boolean addMetaEventListener(MetaEventListener listener); - + boolean addMetaEventListener(MetaEventListener listener); /** - * Removes the specified meta-event listener from this sequencer's - * list of registered listeners, if in fact the listener is registered. + * Removes the specified meta-event listener from this sequencer's list of + * registered listeners, if in fact the listener is registered. * - * @param listener the meta-event listener to remove + * @param listener the meta-event listener to remove * @see #addMetaEventListener */ - public void removeMetaEventListener(MetaEventListener listener); - + void removeMetaEventListener(MetaEventListener listener); /** - * Registers a controller event listener to receive notification - * whenever the sequencer processes a control-change event of the - * requested type or types. The types are specified by the - * controllers argument, which should contain an array of - * MIDI controller numbers. (Each number should be between 0 and 127, - * inclusive. See the MIDI 1.0 Specification for the numbers that - * correspond to various types of controllers.) + * Registers a controller event listener to receive notification whenever + * the sequencer processes a control-change event of the requested type or + * types. The types are specified by the {@code controllers} argument, which + * should contain an array of MIDI controller numbers. (Each number should + * be between 0 and 127, inclusive. See the MIDI 1.0 Specification for the + * numbers that correspond to various types of controllers.) *

    - * The returned array contains the MIDI controller - * numbers for which the listener will now receive events. - * Some sequencers might not support controller event notification, in - * which case the array has a length of 0. Other sequencers might - * support notification for some controllers but not all. - * This method may be invoked repeatedly. - * Each time, the returned array indicates all the controllers - * that the listener will be notified about, not only the controllers - * requested in that particular invocation. - * - * @param listener the controller event listener to add to the list of - * registered listeners - * @param controllers the MIDI controller numbers for which change - * notification is requested - * @return the numbers of all the MIDI controllers whose changes will - * now be reported to the specified listener + * The returned array contains the MIDI controller numbers for which the + * listener will now receive events. Some sequencers might not support + * controller event notification, in which case the array has a length of 0. + * Other sequencers might support notification for some controllers but not + * all. This method may be invoked repeatedly. Each time, the returned array + * indicates all the controllers that the listener will be notified about, + * not only the controllers requested in that particular invocation. * + * @param listener the controller event listener to add to the list of + * registered listeners + * @param controllers the MIDI controller numbers for which change + * notification is requested + * @return the numbers of all the MIDI controllers whose changes will now be + * reported to the specified listener * @see #removeControllerEventListener * @see ControllerEventListener */ - public int[] addControllerEventListener(ControllerEventListener listener, int[] controllers); - + int[] addControllerEventListener(ControllerEventListener listener, + int[] controllers); /** - * Removes a controller event listener's interest in one or more - * types of controller event. The controllers argument - * is an array of MIDI numbers corresponding to the controllers for - * which the listener should no longer receive change notifications. - * To completely remove this listener from the list of registered - * listeners, pass in null for controllers. - * The returned array contains the MIDI controller - * numbers for which the listener will now receive events. The - * array has a length of 0 if the listener will not receive - * change notifications for any controllers. - * - * @param listener old listener - * @param controllers the MIDI controller numbers for which change - * notification should be cancelled, or null to cancel - * for all controllers - * @return the numbers of all the MIDI controllers whose changes will - * now be reported to the specified listener + * Removes a controller event listener's interest in one or more types of + * controller event. The {@code controllers} argument is an array of MIDI + * numbers corresponding to the controllers for which the listener should no + * longer receive change notifications. To completely remove this listener + * from the list of registered listeners, pass in {@code null} for + * {@code controllers}. The returned array contains the MIDI controller + * numbers for which the listener will now receive events. The array has a + * length of 0 if the listener will not receive change notifications for any + * controllers. * + * @param listener old listener + * @param controllers the MIDI controller numbers for which change + * notification should be cancelled, or {@code null} to cancel for + * all controllers + * @return the numbers of all the MIDI controllers whose changes will now be + * reported to the specified listener * @see #addControllerEventListener */ - public int[] removeControllerEventListener(ControllerEventListener listener, int[] controllers); - + int[] removeControllerEventListener(ControllerEventListener listener, + int[] controllers); /** - * Sets the first MIDI tick that will be - * played in the loop. If the loop count is - * greater than 0, playback will jump to this - * point when reaching the loop end point. - * - *

    A value of 0 for the starting point means the - * beginning of the loaded sequence. The starting - * point must be lower than or equal to the ending - * point, and it must fall within the size of the - * loaded sequence. - * - *

    A sequencer's loop start point defaults to - * start of the sequence. - * - * @param tick the loop's starting position, - * in MIDI ticks (zero-based) - * @throws IllegalArgumentException if the requested - * loop start point cannot be set, usually because - * it falls outside the sequence's - * duration or because the start point is - * after the end point + * Sets the first MIDI tick that will be played in the loop. If the loop + * count is greater than 0, playback will jump to this point when reaching + * the loop end point. + *

    + * A value of 0 for the starting point means the beginning of the loaded + * sequence. The starting point must be lower than or equal to the ending + * point, and it must fall within the size of the loaded sequence. + *

    + * A sequencer's loop start point defaults to start of the sequence. * + * @param tick the loop's starting position, in MIDI ticks (zero-based) + * @throws IllegalArgumentException if the requested loop start point cannot + * be set, usually because it falls outside the sequence's duration + * or because the start point is after the end point * @see #setLoopEndPoint * @see #setLoopCount * @see #getLoopStartPoint * @see #start * @since 1.5 */ - public void setLoopStartPoint(long tick); - + void setLoopStartPoint(long tick); /** - * Obtains the start position of the loop, - * in MIDI ticks. + * Obtains the start position of the loop, in MIDI ticks. * - * @return the start position of the loop, - in MIDI ticks (zero-based) + * @return the start position of the loop, in MIDI ticks (zero-based) * @see #setLoopStartPoint * @since 1.5 */ - public long getLoopStartPoint(); - + long getLoopStartPoint(); /** - * Sets the last MIDI tick that will be played in - * the loop. If the loop count is 0, the loop end - * point has no effect and playback continues to + * Sets the last MIDI tick that will be played in the loop. If the loop + * count is 0, the loop end point has no effect and playback continues to * play when reaching the loop end point. + *

    + * A value of -1 for the ending point indicates the last tick of the + * sequence. Otherwise, the ending point must be greater than or equal to + * the starting point, and it must fall within the size of the loaded + * sequence. + *

    + * A sequencer's loop end point defaults to -1, meaning the end of the + * sequence. * - *

    A value of -1 for the ending point - * indicates the last tick of the sequence. - * Otherwise, the ending point must be greater - * than or equal to the starting point, and it must - * fall within the size of the loaded sequence. - * - *

    A sequencer's loop end point defaults to -1, - * meaning the end of the sequence. - * - * @param tick the loop's ending position, - * in MIDI ticks (zero-based), or - * -1 to indicate the final tick - * @throws IllegalArgumentException if the requested - * loop point cannot be set, usually because - * it falls outside the sequence's - * duration or because the ending point is - * before the starting point - * + * @param tick the loop's ending position, in MIDI ticks (zero-based), or + * -1 to indicate the final tick + * @throws IllegalArgumentException if the requested loop point cannot be + * set, usually because it falls outside the sequence's duration or + * because the ending point is before the starting point * @see #setLoopStartPoint * @see #setLoopCount * @see #getLoopEndPoint * @see #start * @since 1.5 */ - public void setLoopEndPoint(long tick); - + void setLoopEndPoint(long tick); /** - * Obtains the end position of the loop, - * in MIDI ticks. + * Obtains the end position of the loop, in MIDI ticks. * - * @return the end position of the loop, in MIDI - * ticks (zero-based), or -1 to indicate - * the end of the sequence + * @return the end position of the loop, in MIDI ticks (zero-based), or -1 + * to indicate the end of the sequence * @see #setLoopEndPoint * @since 1.5 */ - public long getLoopEndPoint(); - + long getLoopEndPoint(); /** - * Sets the number of repetitions of the loop for - * playback. - * When the playback position reaches the loop end point, - * it will loop back to the loop start point - * count times, after which playback will - * continue to play to the end of the sequence. + * Sets the number of repetitions of the loop for playback. When the + * playback position reaches the loop end point, it will loop back to the + * loop start point {@code count} times, after which playback will continue + * to play to the end of the sequence. *

    - * If the current position when this method is invoked - * is greater than the loop end point, playback - * continues to the end of the sequence without looping, - * unless the loop end point is changed subsequently. + * If the current position when this method is invoked is greater than the + * loop end point, playback continues to the end of the sequence without + * looping, unless the loop end point is changed subsequently. *

    - * A count value of 0 disables looping: - * playback will continue at the loop end point, and it - * will not loop back to the loop start point. + * A {@code count} value of 0 disables looping: playback will continue at + * the loop end point, and it will not loop back to the loop start point. * This is a sequencer's default. + *

    + * If playback is stopped during looping, the current loop status is + * cleared; subsequent start requests are not affected by an interrupted + * loop operation. * - *

    If playback is stopped during looping, the - * current loop status is cleared; subsequent start - * requests are not affected by an interrupted loop - * operation. - * - * @param count the number of times playback should - * loop back from the loop's end position - * to the loop's start position, or - * {@link #LOOP_CONTINUOUSLY} - * to indicate that looping should - * continue until interrupted - * - * @throws IllegalArgumentException if count is - * negative and not equal to {@link #LOOP_CONTINUOUSLY} - * + * @param count the number of times playback should loop back from the + * loop's end position to the loop's start position, or + * {@link #LOOP_CONTINUOUSLY} to indicate that looping should + * continue until interrupted + * @throws IllegalArgumentException if {@code count} is negative and not + * equal to {@link #LOOP_CONTINUOUSLY} * @see #setLoopStartPoint * @see #setLoopEndPoint * @see #getLoopCount * @see #start * @since 1.5 */ - public void setLoopCount(int count); - + void setLoopCount(int count); /** - * Obtains the number of repetitions for - * playback. + * Obtains the number of repetitions for playback. * - * @return the number of loops after which - * playback plays to the end of the + * @return the number of loops after which playback plays to the end of the * sequence * @see #setLoopCount * @see #start * @since 1.5 */ - public int getLoopCount(); + int getLoopCount(); /** - * A SyncMode object represents one of the ways in which - * a MIDI sequencer's notion of time can be synchronized with a master - * or slave device. - * If the sequencer is being synchronized to a master, the - * sequencer revises its current time in response to messages from - * the master. If the sequencer has a slave, the sequencer - * similarly sends messages to control the slave's timing. + * A {@code SyncMode} object represents one of the ways in which a MIDI + * sequencer's notion of time can be synchronized with a master or slave + * device. If the sequencer is being synchronized to a master, the sequencer + * revises its current time in response to messages from the master. If the + * sequencer has a slave, the sequencer similarly sends messages to control + * the slave's timing. *

    - * There are three predefined modes that specify possible masters - * for a sequencer: INTERNAL_CLOCK, - * MIDI_SYNC, and MIDI_TIME_CODE. The - * latter two work if the sequencer receives MIDI messages from - * another device. In these two modes, the sequencer's time gets reset - * based on system real-time timing clock messages or MIDI time code - * (MTC) messages, respectively. These two modes can also be used - * as slave modes, in which case the sequencer sends the corresponding - * types of MIDI messages to its receiver (whether or not the sequencer - * is also receiving them from a master). A fourth mode, - * NO_SYNC, is used to indicate that the sequencer should - * not control its receiver's timing. + * There are three predefined modes that specify possible masters for a + * sequencer: {@code INTERNAL_CLOCK}, {@code MIDI_SYNC}, and + * {@code MIDI_TIME_CODE}. The latter two work if the sequencer receives + * MIDI messages from another device. In these two modes, the sequencer's + * time gets reset based on system real-time timing clock messages or MIDI + * time code (MTC) messages, respectively. These two modes can also be used + * as slave modes, in which case the sequencer sends the corresponding types + * of MIDI messages to its receiver (whether or not the sequencer is also + * receiving them from a master). A fourth mode, {@code NO_SYNC}, is used to + * indicate that the sequencer should not control its receiver's timing. * - * @see Sequencer#setMasterSyncMode(Sequencer.SyncMode) - * @see Sequencer#setSlaveSyncMode(Sequencer.SyncMode) + * @see Sequencer#setMasterSyncMode(SyncMode) + * @see Sequencer#setSlaveSyncMode(SyncMode) */ - public static class SyncMode { + class SyncMode { /** * Synchronization mode name. @@ -779,27 +684,27 @@ public interface Sequencer extends MidiDevice { /** * Constructs a synchronization mode. - * @param name name of the synchronization mode + * + * @param name name of the synchronization mode */ protected SyncMode(String name) { this.name = name; } - /** - * Determines whether two objects are equal. - * Returns true if the objects are identical - * @param obj the reference object with which to compare - * @return true if this object is the same as the - * obj argument, false otherwise + * Determines whether two objects are equal. Returns {@code true} if the + * objects are identical. + * + * @param obj the reference object with which to compare + * @return {@code true} if this object is the same as the {@code obj} + * argument, {@code false} otherwise */ public final boolean equals(Object obj) { return super.equals(obj); } - /** * Finalizes the hashcode method. */ @@ -808,10 +713,10 @@ public interface Sequencer extends MidiDevice { return super.hashCode(); } - /** * Provides this synchronization mode's name as the string * representation of the mode. + * * @return the name of this synchronization mode */ public final String toString() { @@ -819,50 +724,41 @@ public interface Sequencer extends MidiDevice { return name; } - /** - * A master synchronization mode that makes the sequencer get - * its timing information from its internal clock. This is not - * a legal slave sync mode. + * A master synchronization mode that makes the sequencer get its timing + * information from its internal clock. This is not a legal slave sync + * mode. */ public static final SyncMode INTERNAL_CLOCK = new SyncMode("Internal Clock"); - /** - * A master or slave synchronization mode that specifies the - * use of MIDI clock - * messages. If this mode is used as the master sync mode, - * the sequencer gets its timing information from system real-time - * MIDI clock messages. This mode only applies as the master sync - * mode for sequencers that are also MIDI receivers. If this is the - * slave sync mode, the sequencer sends system real-time MIDI clock - * messages to its receiver. MIDI clock messages are sent at a rate - * of 24 per quarter note. + * A master or slave synchronization mode that specifies the use of MIDI + * clock messages. If this mode is used as the master sync mode, the + * sequencer gets its timing information from system real-time MIDI + * clock messages. This mode only applies as the master sync mode for + * sequencers that are also MIDI receivers. If this is the slave sync + * mode, the sequencer sends system real-time MIDI clock messages to its + * receiver. MIDI clock messages are sent at a rate of 24 per quarter + * note. */ public static final SyncMode MIDI_SYNC = new SyncMode("MIDI Sync"); - /** - * A master or slave synchronization mode that specifies the - * use of MIDI Time Code. - * If this mode is used as the master sync mode, - * the sequencer gets its timing information from MIDI Time Code - * messages. This mode only applies as the master sync - * mode to sequencers that are also MIDI receivers. If this - * mode is used as the - * slave sync mode, the sequencer sends MIDI Time Code - * messages to its receiver. (See the MIDI 1.0 Detailed - * Specification for a description of MIDI Time Code.) + * A master or slave synchronization mode that specifies the use of MIDI + * Time Code. If this mode is used as the master sync mode, the + * sequencer gets its timing information from MIDI Time Code messages. + * This mode only applies as the master sync mode to sequencers that are + * also MIDI receivers. If this mode is used as the slave sync mode, the + * sequencer sends MIDI Time Code messages to its receiver. (See the + * MIDI 1.0 Detailed Specification for a description of MIDI Time Code.) */ public static final SyncMode MIDI_TIME_CODE = new SyncMode("MIDI Time Code"); - /** * A slave synchronization mode indicating that no timing information - * should be sent to the receiver. This is not a legal master sync - * mode. + * should be sent to the receiver. This is not a legal master sync mode. */ public static final SyncMode NO_SYNC = new SyncMode("No Timing"); - } // class SyncMode + } } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/ShortMessage.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/ShortMessage.java index 02301ca2a49..8dcf92f9552 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/ShortMessage.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/ShortMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,156 +26,158 @@ package javax.sound.midi; /** - * A ShortMessage contains a MIDI message that has at most - * two data bytes following its status byte. The types of MIDI message - * that satisfy this criterion are channel voice, channel mode, system common, - * and system real-time--in other words, everything except system exclusive - * and meta-events. The ShortMessage class provides methods - * for getting and setting the contents of the MIDI message. + * A {@code ShortMessage} contains a MIDI message that has at most two data + * bytes following its status byte. The types of MIDI message that satisfy this + * criterion are channel voice, channel mode, system common, and system + * real-time--in other words, everything except system exclusive and + * meta-events. The {@code ShortMessage} class provides methods for getting and + * setting the contents of the MIDI message. *

    - * A number of ShortMessage methods have integer parameters by which - * you specify a MIDI status or data byte. If you know the numeric value, you - * can express it directly. For system common and system real-time messages, - * you can often use the corresponding fields of ShortMessage, such as - * {@link #SYSTEM_RESET SYSTEM_RESET}. For channel messages, - * the upper four bits of the status byte are specified by a command value and - * the lower four bits are specified by a MIDI channel number. To - * convert incoming MIDI data bytes that are in the form of Java's signed bytes, - * you can use the conversion code - * given in the {@link MidiMessage} class description. - * - * @see SysexMessage - * @see MetaMessage + * A number of {@code ShortMessage} methods have integer parameters by which you + * specify a MIDI status or data byte. If you know the numeric value, you can + * express it directly. For system common and system real-time messages, you can + * often use the corresponding fields of {@code ShortMessage}, such as + * {@link #SYSTEM_RESET SYSTEM_RESET}. For channel messages, the upper four bits + * of the status byte are specified by a command value and the lower four bits + * are specified by a MIDI channel number. To convert incoming MIDI data bytes + * that are in the form of Java's signed bytes, you can use the + * conversion code given in the + * {@link MidiMessage} class description. * * @author David Rivas * @author Kara Kytle * @author Florian Bomers + * @see SysexMessage + * @see MetaMessage */ - public class ShortMessage extends MidiMessage { - // Status byte defines - // System common messages /** * Status byte for MIDI Time Code Quarter Frame message (0xF1, or 241). + * * @see MidiMessage#getStatus */ public static final int MIDI_TIME_CODE = 0xF1; // 241 /** * Status byte for Song Position Pointer message (0xF2, or 242). + * * @see MidiMessage#getStatus */ public static final int SONG_POSITION_POINTER = 0xF2; // 242 /** * Status byte for MIDI Song Select message (0xF3, or 243). + * * @see MidiMessage#getStatus */ public static final int SONG_SELECT = 0xF3; // 243 /** * Status byte for Tune Request message (0xF6, or 246). + * * @see MidiMessage#getStatus */ public static final int TUNE_REQUEST = 0xF6; // 246 /** * Status byte for End of System Exclusive message (0xF7, or 247). + * * @see MidiMessage#getStatus */ public static final int END_OF_EXCLUSIVE = 0xF7; // 247 - // System real-time messages /** * Status byte for Timing Clock message (0xF8, or 248). + * * @see MidiMessage#getStatus */ public static final int TIMING_CLOCK = 0xF8; // 248 /** * Status byte for Start message (0xFA, or 250). + * * @see MidiMessage#getStatus */ public static final int START = 0xFA; // 250 /** * Status byte for Continue message (0xFB, or 251). + * * @see MidiMessage#getStatus */ public static final int CONTINUE = 0xFB; // 251 /** * Status byte for Stop message (0xFC, or 252). + * * @see MidiMessage#getStatus */ public static final int STOP = 0xFC; //252 /** * Status byte for Active Sensing message (0xFE, or 254). + * * @see MidiMessage#getStatus */ public static final int ACTIVE_SENSING = 0xFE; // 254 /** * Status byte for System Reset message (0xFF, or 255). + * * @see MidiMessage#getStatus */ public static final int SYSTEM_RESET = 0xFF; // 255 - // Channel voice message upper nibble defines /** - * Command value for Note Off message (0x80, or 128) + * Command value for Note Off message (0x80, or 128). */ public static final int NOTE_OFF = 0x80; // 128 /** - * Command value for Note On message (0x90, or 144) + * Command value for Note On message (0x90, or 144). */ public static final int NOTE_ON = 0x90; // 144 /** - * Command value for Polyphonic Key Pressure (Aftertouch) message (0xA0, or 160) + * Command value for Polyphonic Key Pressure (Aftertouch) message (0xA0, or + * 160). */ public static final int POLY_PRESSURE = 0xA0; // 160 /** - * Command value for Control Change message (0xB0, or 176) + * Command value for Control Change message (0xB0, or 176). */ public static final int CONTROL_CHANGE = 0xB0; // 176 /** - * Command value for Program Change message (0xC0, or 192) + * Command value for Program Change message (0xC0, or 192). */ public static final int PROGRAM_CHANGE = 0xC0; // 192 /** - * Command value for Channel Pressure (Aftertouch) message (0xD0, or 208) + * Command value for Channel Pressure (Aftertouch) message (0xD0, or 208). */ public static final int CHANNEL_PRESSURE = 0xD0; // 208 /** - * Command value for Pitch Bend message (0xE0, or 224) + * Command value for Pitch Bend message (0xE0, or 224). */ public static final int PITCH_BEND = 0xE0; // 224 - - // Instance variables - /** - * Constructs a new ShortMessage. The - * contents of the new message are guaranteed to specify - * a valid MIDI message. Subsequently, you may set the - * contents of the message using one of the setMessage - * methods. + * Constructs a new {@code ShortMessage}. The contents of the new message + * are guaranteed to specify a valid MIDI message. Subsequently, you may set + * the contents of the message using one of the {@code setMessage} methods. + * * @see #setMessage */ public ShortMessage() { @@ -188,14 +190,13 @@ public class ShortMessage extends MidiMessage { } /** - * Constructs a new {@code ShortMessage} which represents a MIDI - * message that takes no data bytes. - * The contents of the message can be changed by using one of - * the {@code setMessage} methods. + * Constructs a new {@code ShortMessage} which represents a MIDI message + * that takes no data bytes. The contents of the message can be changed by + * using one of the {@code setMessage} methods. * - * @param status the MIDI status byte - * @throws InvalidMidiDataException if {@code status} does not specify - * a valid MIDI status byte for a message that requires no data bytes + * @param status the MIDI status byte + * @throws InvalidMidiDataException if {@code status} does not specify a + * valid MIDI status byte for a message that requires no data bytes * @see #setMessage(int) * @see #setMessage(int, int, int) * @see #setMessage(int, int, int, int) @@ -210,16 +211,15 @@ public class ShortMessage extends MidiMessage { /** * Constructs a new {@code ShortMessage} which represents a MIDI message * that takes up to two data bytes. If the message only takes one data byte, - * the second data byte is ignored. If the message does not take - * any data bytes, both data bytes are ignored. - * The contents of the message can be changed by using one of - * the {@code setMessage} methods. + * the second data byte is ignored. If the message does not take any data + * bytes, both data bytes are ignored. The contents of the message can be + * changed by using one of the {@code setMessage} methods. * - * @param status the MIDI status byte - * @param data1 the first data byte - * @param data2 the second data byte + * @param status the MIDI status byte + * @param data1 the first data byte + * @param data2 the second data byte * @throws InvalidMidiDataException if the status byte or all data bytes - * belonging to the message do not specify a valid MIDI message + * belonging to the message do not specify a valid MIDI message * @see #setMessage(int) * @see #setMessage(int, int, int) * @see #setMessage(int, int, int, int) @@ -235,20 +235,19 @@ public class ShortMessage extends MidiMessage { } /** - * Constructs a new {@code ShortMessage} which represents a channel - * MIDI message that takes up to two data bytes. If the message only takes - * one data byte, the second data byte is ignored. If the message does not - * take any data bytes, both data bytes are ignored. - * The contents of the message can be changed by using one of - * the {@code setMessage} methods. + * Constructs a new {@code ShortMessage} which represents a channel MIDI + * message that takes up to two data bytes. If the message only takes one + * data byte, the second data byte is ignored. If the message does not take + * any data bytes, both data bytes are ignored. The contents of the message + * can be changed by using one of the {@code setMessage} methods. * - * @param command the MIDI command represented by this message - * @param channel the channel associated with the message - * @param data1 the first data byte - * @param data2 the second data byte - * @throws InvalidMidiDataException if the command value, channel value - * or all data bytes belonging to the message do not specify - * a valid MIDI message + * @param command the MIDI command represented by this message + * @param channel the channel associated with the message + * @param data1 the first data byte + * @param data2 the second data byte + * @throws InvalidMidiDataException if the command value, channel value or + * all data bytes belonging to the message do not specify a valid + * MIDI message * @see #setMessage(int) * @see #setMessage(int, int, int) * @see #setMessage(int, int, int, int) @@ -264,12 +263,11 @@ public class ShortMessage extends MidiMessage { setMessage(command, channel, data1, data2); } - /** - * Constructs a new ShortMessage. - * @param data an array of bytes containing the complete message. - * The message data may be changed using the setMessage - * method. + * Constructs a new {@code ShortMessage}. + * + * @param data an array of bytes containing the complete message. The + * message data may be changed using the {@code setMessage} method. * @see #setMessage */ // $$fb this should throw an Exception in case of an illegal message! @@ -279,12 +277,12 @@ public class ShortMessage extends MidiMessage { super(data); } - /** * Sets the parameters for a MIDI message that takes no data bytes. - * @param status the MIDI status byte - * @throws InvalidMidiDataException if status does not - * specify a valid MIDI status byte for a message that requires no data bytes. + * + * @param status the MIDI status byte + * @throws InvalidMidiDataException if {@code status} does not specify a + * valid MIDI status byte for a message that requires no data bytes * @see #setMessage(int, int, int) * @see #setMessage(int, int, int, int) */ @@ -297,19 +295,17 @@ public class ShortMessage extends MidiMessage { setMessage(status, 0, 0); } - /** - * Sets the parameters for a MIDI message that takes one or two data - * bytes. If the message takes only one data byte, the second data - * byte is ignored; if the message does not take any data bytes, both - * data bytes are ignored. + * Sets the parameters for a MIDI message that takes one or two data bytes. + * If the message takes only one data byte, the second data byte is ignored; + * if the message does not take any data bytes, both data bytes are ignored. * - * @param status the MIDI status byte - * @param data1 the first data byte - * @param data2 the second data byte - * @throws InvalidMidiDataException if the - * the status byte, or all data bytes belonging to the message, do - * not specify a valid MIDI message. + * @param status the MIDI status byte + * @param data1 the first data byte + * @param data2 the second data byte + * @throws InvalidMidiDataException if the the status byte, or all data + * bytes belonging to the message, do not specify a valid MIDI + * message * @see #setMessage(int, int, int, int) * @see #setMessage(int) */ @@ -345,22 +341,18 @@ public class ShortMessage extends MidiMessage { } } - /** - * Sets the short message parameters for a channel message - * which takes up to two data bytes. If the message only - * takes one data byte, the second data byte is ignored; if - * the message does not take any data bytes, both data bytes - * are ignored. - * - * @param command the MIDI command represented by this message - * @param channel the channel associated with the message - * @param data1 the first data byte - * @param data2 the second data byte - * @throws InvalidMidiDataException if the - * status byte or all data bytes belonging to the message, do - * not specify a valid MIDI message + * Sets the short message parameters for a channel message which takes up to + * two data bytes. If the message only takes one data byte, the second data + * byte is ignored; if the message does not take any data bytes, both data + * bytes are ignored. * + * @param command the MIDI command represented by this message + * @param channel the channel associated with the message + * @param data1 the first data byte + * @param data2 the second data byte + * @throws InvalidMidiDataException if the status byte or all data bytes + * belonging to the message, do not specify a valid MIDI message * @see #setMessage(int, int, int) * @see #setMessage(int) * @see #getCommand @@ -379,12 +371,12 @@ public class ShortMessage extends MidiMessage { setMessage((command & 0xF0) | (channel & 0x0F), data1, data2); } - /** - * Obtains the MIDI channel associated with this event. This method - * assumes that the event is a MIDI channel message; if not, the return - * value will not be meaningful. - * @return MIDI channel associated with the message. + * Obtains the MIDI channel associated with this event. This method assumes + * that the event is a MIDI channel message; if not, the return value will + * not be meaningful. + * + * @return MIDI channel associated with the message * @see #setMessage(int, int, int, int) */ public int getChannel() { @@ -392,11 +384,11 @@ public class ShortMessage extends MidiMessage { return (getStatus() & 0x0F); } - /** - * Obtains the MIDI command associated with this event. This method - * assumes that the event is a MIDI channel message; if not, the return - * value will not be meaningful. + * Obtains the MIDI command associated with this event. This method assumes + * that the event is a MIDI channel message; if not, the return value will + * not be meaningful. + * * @return the MIDI command associated with this event * @see #setMessage(int, int, int, int) */ @@ -405,10 +397,10 @@ public class ShortMessage extends MidiMessage { return (getStatus() & 0xF0); } - /** * Obtains the first data byte in the message. - * @return the value of the data1 field + * + * @return the value of the {@code data1} field * @see #setMessage(int, int, int) */ public int getData1() { @@ -418,10 +410,10 @@ public class ShortMessage extends MidiMessage { return 0; } - /** * Obtains the second data byte in the message. - * @return the value of the data2 field + * + * @return the value of the {@code data2} field * @see #setMessage(int, int, int) */ public int getData2() { @@ -431,11 +423,11 @@ public class ShortMessage extends MidiMessage { return 0; } - /** - * Creates a new object of the same class and with the same contents - * as this object. - * @return a clone of this instance. + * Creates a new object of the same class and with the same contents as this + * object. + * + * @return a clone of this instance */ public Object clone() { byte[] newData = new byte[length]; @@ -445,15 +437,15 @@ public class ShortMessage extends MidiMessage { return msg; } - /** - * Retrieves the number of data bytes associated with a particular - * status byte value. - * @param status status byte value, which must represent a short MIDI message + * Retrieves the number of data bytes associated with a particular status + * byte value. + * + * @param status status byte value, which must represent a short MIDI + * message * @return data length in bytes (0, 1, or 2) - * @throws InvalidMidiDataException if the - * status argument does not represent the status byte for any - * short message + * @throws InvalidMidiDataException if the {@code status} argument does not + * represent the status byte for any short message */ protected final int getDataLength(int status) throws InvalidMidiDataException { // system common and system real-time messages diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/Soundbank.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/Soundbank.java index 7aba05711c9..727365ea442 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/Soundbank.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/Soundbank.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,109 +25,101 @@ package javax.sound.midi; -import java.net.URL; - - /** - * A Soundbank contains a set of Instruments - * that can be loaded into a Synthesizer. - * Note that a Java Sound Soundbank is different from a MIDI bank. - * MIDI permits up to 16383 banks, each containing up to 128 instruments - * (also sometimes called programs, patches, or timbres). - * However, a Soundbank can contain 16383 times 128 instruments, - * because the instruments within a Soundbank are indexed by both - * a MIDI program number and a MIDI bank number (via a Patch - * object). Thus, a Soundbank can be thought of as a collection - * of MIDI banks. + * A {@code Soundbank} contains a set of {@code Instruments} that can be loaded + * into a {@code Synthesizer}. Note that a Java Sound {@code Soundbank} is + * different from a MIDI bank. MIDI permits up to 16383 banks, each containing + * up to 128 instruments (also sometimes called programs, patches, or timbres). + * However, a {@code Soundbank} can contain 16383 times 128 instruments, because + * the instruments within a {@code Soundbank} are indexed by both a MIDI program + * number and a MIDI bank number (via a {@code Patch} object). Thus, a + * {@code Soundbank} can be thought of as a collection of MIDI banks. *

    - * Soundbank includes methods that return String - * objects containing the sound bank's name, manufacturer, version number, and - * description. The precise content and format of these strings is left - * to the implementor. + * {@code Soundbank} includes methods that return {@code String} objects + * containing the sound bank's name, manufacturer, version number, and + * description. The precise content and format of these strings is left to the + * implementor. *

    - * Different synthesizers use a variety of synthesis techniques. A common - * one is wavetable synthesis, in which a segment of recorded sound is - * played back, often with looping and pitch change. The Downloadable Sound - * (DLS) format uses segments of recorded sound, as does the Headspace Engine. - * Soundbanks and Instruments that are based on - * wavetable synthesis (or other uses of stored sound recordings) should - * typically implement the getResources() - * method to provide access to these recorded segments. This is optional, - * however; the method can return an zero-length array if the synthesis technique - * doesn't use sampled sound (FM synthesis and physical modeling are examples - * of such techniques), or if it does but the implementor chooses not to make the - * samples accessible. + * Different synthesizers use a variety of synthesis techniques. A common one is + * wavetable synthesis, in which a segment of recorded sound is played back, + * often with looping and pitch change. The Downloadable Sound (DLS) format uses + * segments of recorded sound, as does the Headspace Engine. {@code Soundbanks} + * and {@code Instruments} that are based on wavetable synthesis (or other uses + * of stored sound recordings) should typically implement the + * {@code getResources()} method to provide access to these recorded segments. + * This is optional, however; the method can return an zero-length array if the + * synthesis technique doesn't use sampled sound (FM synthesis and physical + * modeling are examples of such techniques), or if it does but the implementor + * chooses not to make the samples accessible. * + * @author David Rivas + * @author Kara Kytle * @see Synthesizer#getDefaultSoundbank * @see Synthesizer#isSoundbankSupported * @see Synthesizer#loadInstruments(Soundbank, Patch[]) * @see Patch * @see Instrument * @see SoundbankResource - * - * @author David Rivas - * @author Kara Kytle */ - public interface Soundbank { - /** * Obtains the name of the sound bank. - * @return a String naming the sound bank + * + * @return a {@code String} naming the sound bank */ - public String getName(); + String getName(); /** * Obtains the version string for the sound bank. - * @return a String that indicates the sound bank's version + * + * @return a {@code String} that indicates the sound bank's version */ - public String getVersion(); + String getVersion(); /** - * Obtains a string naming the company that provides the - * sound bank + * Obtains a {@code string} naming the company that provides the sound bank. + * * @return the vendor string */ - public String getVendor(); + String getVendor(); /** * Obtains a textual description of the sound bank, suitable for display. - * @return a String that describes the sound bank + * + * @return a {@code String} that describes the sound bank */ - public String getDescription(); - + String getDescription(); /** * Extracts a list of non-Instrument resources contained in the sound bank. - * @return an array of resources, excluding instruments. If the sound bank contains - * no resources (other than instruments), returns an array of length 0. + * + * @return an array of resources, excluding instruments. If the sound bank + * contains no resources (other than instruments), returns an array + * of length 0. */ - public SoundbankResource[] getResources(); - + SoundbankResource[] getResources(); /** * Obtains a list of instruments contained in this sound bank. - * @return an array of the Instruments in this - * SoundBank - * If the sound bank contains no instruments, returns an array of length 0. * + * @return an array of the {@code Instruments} in this {@code SoundBank}. If + * the sound bank contains no instruments, returns an array of + * length 0. * @see Synthesizer#getLoadedInstruments * @see #getInstrument(Patch) */ - public Instrument[] getInstruments(); + Instrument[] getInstruments(); /** - * Obtains an Instrument from the given Patch. - * @param patch a Patch object specifying the bank index - * and program change number - * @return the requested instrument, or null if the - * sound bank doesn't contain that instrument + * Obtains an {@code Instrument} from the given {@code Patch}. * + * @param patch a {@code Patch} object specifying the bank index and + * program change number + * @return the requested instrument, or {@code null} if the sound bank + * doesn't contain that instrument * @see #getInstruments * @see Synthesizer#loadInstruments(Soundbank, Patch[]) */ - public Instrument getInstrument(Patch patch); - - + Instrument getInstrument(Patch patch); } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/SoundbankResource.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/SoundbankResource.java index 52ba8f78feb..8ac530105eb 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/SoundbankResource.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/SoundbankResource.java @@ -25,81 +25,72 @@ package javax.sound.midi; +import javax.sound.sampled.AudioInputStream; + /** - * A SoundbankResource represents any audio resource stored - * in a {@link Soundbank}. Common soundbank resources include: + * A {@code SoundbankResource} represents any audio resource stored in a + * {@link Soundbank}. Common soundbank resources include: *

      - *
    • Instruments. An instrument may be specified in a variety of - * ways. However, all soundbanks have some mechanism for defining - * instruments. In doing so, they may reference other resources - * stored in the soundbank. Each instrument has a Patch - * which specifies the MIDI program and bank by which it may be - * referenced in MIDI messages. Instrument information may be - * stored in {@link Instrument} objects. - *
    • Audio samples. A sample typically is a sampled audio waveform - * which contains a short sound recording whose duration is a fraction of - * a second, or at most a few seconds. These audio samples may be - * used by a {@link Synthesizer} to synthesize sound in response to MIDI - * commands, or extracted for use by an application. - * (The terminology reflects musicians' use of the word "sample" to refer - * collectively to a series of contiguous audio samples or frames, rather than - * to a single, instantaneous sample.) - * The data class for an audio sample will be an object - * that encapsulates the audio sample data itself and information - * about how to interpret it (the format of the audio data), such - * as an {@link javax.sound.sampled.AudioInputStream}.
    • - *
    • Embedded sequences. A sound bank may contain built-in - * song data stored in a data object such as a {@link Sequence}. + *
    • Instruments. An instrument may be specified in a variety of ways. + * However, all soundbanks have some mechanism for defining instruments. In + * doing so, they may reference other resources stored in the soundbank. Each + * instrument has a {@code Patch} which specifies the MIDI program and bank by + * which it may be referenced in MIDI messages. Instrument information may be + * stored in {@link Instrument} objects.
    • + *
    • Audio samples. A sample typically is a sampled audio waveform which + * contains a short sound recording whose duration is a fraction of a second, or + * at most a few seconds. These audio samples may be used by a + * {@link Synthesizer} to synthesize sound in response to MIDI commands, or + * extracted for use by an application. (The terminology reflects musicians' use + * of the word "sample" to refer collectively to a series of contiguous audio + * samples or frames, rather than to a single, instantaneous sample.) The data + * class for an audio sample will be an object that encapsulates the audio + * sample data itself and information about how to interpret it (the format of + * the audio data), such as an {@link AudioInputStream}.
    • + *
    • Embedded sequences. A sound bank may contain built-in song data stored in + * a data object such as a {@link Sequence}.
    • *
    - *

    - * Synthesizers that use wavetable synthesis or related - * techniques play back the audio in a sample when - * synthesizing notes, often when emulating the real-world instrument that - * was originally recorded. However, there is not necessarily a one-to-one - * correspondence between the Instruments and samples - * in a Soundbank. A single Instrument can use - * multiple SoundbankResources (typically for notes of dissimilar pitch or - * brightness). Also, more than one Instrument can use the same - * sample. + * Synthesizers that use wavetable synthesis or related techniques play back the + * audio in a sample when synthesizing notes, often when emulating the + * real-world instrument that was originally recorded. However, there is not + * necessarily a one-to-one correspondence between the {@code Instruments} and + * samples in a {@code Soundbank}. A single {@code Instrument} can use multiple + * SoundbankResources (typically for notes of dissimilar pitch or brightness). + * Also, more than one {@code Instrument} can use the same sample. * * @author Kara Kytle */ - public abstract class SoundbankResource { - /** - * The sound bank that contains the SoundbankResources + * The sound bank that contains the {@code SoundbankResources}. */ private final Soundbank soundBank; - /** - * The name of the SoundbankResource + * The name of the {@code SoundbankResource}. */ private final String name; - /** * The class used to represent the sample's data. */ private final Class dataClass; - /** * The wavetable index. */ //private final int index; - /** - * Constructs a new SoundbankResource from the given sound bank - * and wavetable index. (Setting the SoundbankResource's name, - * sampled audio data, and instruments is a subclass responsibility.) - * @param soundBank the sound bank containing this SoundbankResource - * @param name the name of the sample - * @param dataClass the class used to represent the sample's data + * Constructs a new {@code SoundbankResource} from the given sound bank and + * wavetable index. (Setting the {@code SoundbankResource's} name, sampled + * audio data, and instruments is a subclass responsibility.) * + * @param soundBank the sound bank containing this + * {@code SoundbankResource} + * @param name the name of the sample + * @param dataClass the class used to represent the sample's data * @see #getSoundbank * @see #getName * @see #getDataClass @@ -112,65 +103,65 @@ public abstract class SoundbankResource { this.dataClass = dataClass; } - /** - * Obtains the sound bank that contains this SoundbankResource. - * @return the sound bank in which this SoundbankResource is stored + * Obtains the sound bank that contains this {@code SoundbankResource}. + * + * @return the sound bank in which this {@code SoundbankResource} is stored */ public Soundbank getSoundbank() { return soundBank; } - /** - * Obtains the name of the resource. This should generally be a string + * Obtains the name of the resource. This should generally be a string * descriptive of the resource. + * * @return the instrument's name */ public String getName() { return name; } - /** - * Obtains the class used by this sample to represent its data. - * The object returned by getData will be of this - * class. If this SoundbankResource object does not support - * direct access to its data, returns null. - * @return the class used to represent the sample's data, or - * null if the data is not accessible + * Obtains the class used by this sample to represent its data. The object + * returned by {@code getData} will be of this class. If this + * {@code SoundbankResource} object does not support direct access to its + * data, returns {@code null}. + * + * @return the class used to represent the sample's data, or null if the + * data is not accessible */ public Class getDataClass() { return dataClass; } - /** - * Obtains the sampled audio that is stored in this SoundbankResource. - * The type of object returned depends on the implementation of the - * concrete class, and may be queried using getDataClass. + * Obtains the sampled audio that is stored in this + * {@code SoundbankResource}. The type of object returned depends on the + * implementation of the concrete class, and may be queried using + * {@code getDataClass}. + * * @return an object containing the sampled audio data * @see #getDataClass */ public abstract Object getData(); - /** - * Obtains the index of this SoundbankResource into the - * Soundbank's set of SoundbankResources. + * Obtains the index of this {@code SoundbankResource} into the + * {@code Soundbank's} set of {@code SoundbankResources}. + * * @return the wavetable index */ //public int getIndex() { // return index; //} - /** * Obtains a list of the instruments in the sound bank that use the - * SoundbankResource for sound synthesis. - * @return an array of Instruments that reference this - * SoundbankResource + * {@code SoundbankResource} for sound synthesis. * + * @return an array of {@code Instruments} that reference this + * {@code SoundbankResource} * @see Instrument#getSamples */ //public abstract Instrument[] getInstruments(); diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/Synthesizer.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/Synthesizer.java index 6763a969504..3d8c7a64d23 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/Synthesizer.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/Synthesizer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,46 +25,43 @@ package javax.sound.midi; -import javax.sound.sampled.Control; - - /** - * A Synthesizer generates sound. This usually happens when one of - * the Synthesizer's {@link MidiChannel} objects receives a - * {@link MidiChannel#noteOn(int, int) noteOn} message, either - * directly or via the Synthesizer object. - * Many Synthesizers support Receivers, through which - * MIDI events can be delivered to the Synthesizer. - * In such cases, the Synthesizer typically responds by sending - * a corresponding message to the appropriate MidiChannel, or by - * processing the event itself if the event isn't one of the MIDI channel - * messages. + * A {@code Synthesizer} generates sound. This usually happens when one of the + * {@code Synthesizer}'s {@link MidiChannel} objects receives a + * {@link MidiChannel#noteOn(int, int) noteOn} message, either directly or via + * the {@code Synthesizer} object. Many {@code Synthesizer}s support + * {@code Receivers}, through which MIDI events can be delivered to the + * {@code Synthesizer}. In such cases, the {@code Synthesizer} typically + * responds by sending a corresponding message to the appropriate + * {@code MidiChannel}, or by processing the event itself if the event isn't one + * of the MIDI channel messages. *

    - * The Synthesizer interface includes methods for loading and - * unloading instruments from soundbanks. An instrument is a specification for synthesizing a - * certain type of sound, whether that sound emulates a traditional instrument or is - * some kind of sound effect or other imaginary sound. A soundbank is a collection of instruments, organized - * by bank and program number (via the instrument's Patch object). - * Different Synthesizer classes might implement different sound-synthesis - * techniques, meaning that some instruments and not others might be compatible with a - * given synthesizer. - * Also, synthesizers may have a limited amount of memory for instruments, meaning - * that not every soundbank and instrument can be used by every synthesizer, even if - * the synthesis technique is compatible. - * To see whether the instruments from - * a certain soundbank can be played by a given synthesizer, invoke the - * {@link #isSoundbankSupported(Soundbank) isSoundbankSupported} method of - * Synthesizer. + * The {@code Synthesizer} interface includes methods for loading and unloading + * instruments from soundbanks. An instrument is a specification for + * synthesizing a certain type of sound, whether that sound emulates a + * traditional instrument or is some kind of sound effect or other imaginary + * sound. A soundbank is a collection of instruments, organized by bank and + * program number (via the instrument's {@code Patch} object). Different + * {@code Synthesizer} classes might implement different sound-synthesis + * techniques, meaning that some instruments and not others might be compatible + * with a given synthesizer. Also, synthesizers may have a limited amount of + * memory for instruments, meaning that not every soundbank and instrument can + * be used by every synthesizer, even if the synthesis technique is compatible. + * To see whether the instruments from a certain soundbank can be played by a + * given synthesizer, invoke the + * {@link #isSoundbankSupported(Soundbank) isSoundbankSupported} + * method of {@code Synthesizer}. *

    * "Loading" an instrument means that that instrument becomes available for - * synthesizing notes. The instrument is loaded into the bank and - * program location specified by its Patch object. Loading does - * not necessarily mean that subsequently played notes will immediately have - * the sound of this newly loaded instrument. For the instrument to play notes, - * one of the synthesizer's MidiChannel objects must receive (or have received) - * a program-change message that causes that particular instrument's - * bank and program number to be selected. + * synthesizing notes. The instrument is loaded into the bank and program + * location specified by its {@code Patch} object. Loading does not necessarily + * mean that subsequently played notes will immediately have the sound of this + * newly loaded instrument. For the instrument to play notes, one of the + * synthesizer's {@code MidiChannel} objects must receive (or have received) a + * program-change message that causes that particular instrument's bank and + * program number to be selected. * + * @author Kara Kytle * @see MidiSystem#getSynthesizer * @see Soundbank * @see Instrument @@ -72,107 +69,103 @@ import javax.sound.sampled.Control; * @see Receiver * @see Transmitter * @see MidiDevice - * - * @author Kara Kytle */ public interface Synthesizer extends MidiDevice { - // SYNTHESIZER METHODS - /** - * Obtains the maximum number of notes that this synthesizer can sound simultaneously. + * Obtains the maximum number of notes that this synthesizer can sound + * simultaneously. + * * @return the maximum number of simultaneous notes * @see #getVoiceStatus */ - public int getMaxPolyphony(); - + int getMaxPolyphony(); /** * Obtains the processing latency incurred by this synthesizer, expressed in - * microseconds. This latency measures the worst-case delay between the - * time a MIDI message is delivered to the synthesizer and the time that the + * microseconds. This latency measures the worst-case delay between the time + * a MIDI message is delivered to the synthesizer and the time that the * synthesizer actually produces the corresponding result. *

    - * Although the latency is expressed in microseconds, a synthesizer's actual measured - * delay may vary over a wider range than this resolution suggests. For example, - * a synthesizer might have a worst-case delay of a few milliseconds or more. + * Although the latency is expressed in microseconds, a synthesizer's actual + * measured delay may vary over a wider range than this resolution suggests. + * For example, a synthesizer might have a worst-case delay of a few + * milliseconds or more. * * @return the worst-case delay, in microseconds */ - public long getLatency(); - + long getLatency(); /** - * Obtains the set of MIDI channels controlled by this synthesizer. Each - * non-null element in the returned array is a MidiChannel that + * Obtains the set of MIDI channels controlled by this synthesizer. Each + * non-null element in the returned array is a {@code MidiChannel} that * receives the MIDI messages sent on that channel number. *

    - * The MIDI 1.0 specification provides for 16 channels, so this - * method returns an array of at least 16 elements. However, if this synthesizer + * The MIDI 1.0 specification provides for 16 channels, so this method + * returns an array of at least 16 elements. However, if this synthesizer * doesn't make use of all 16 channels, some of the elements of the array - * might be null, so you should check each element - * before using it. - * @return an array of the MidiChannel objects managed by this - * Synthesizer. Some of the array elements may be null. + * might be {@code null}, so you should check each element before using it. + * + * @return an array of the {@code MidiChannel} objects managed by this + * {@code Synthesizer}. Some of the array elements may be + * {@code null}. */ - public MidiChannel[] getChannels(); - + MidiChannel[] getChannels(); /** - * Obtains the current status of the voices produced by this synthesizer. - * If this class of Synthesizer does not provide voice - * information, the returned array will always be of length 0. Otherwise, - * its length is always equal to the total number of voices, as returned by - * getMaxPolyphony(). (See the VoiceStatus class - * description for an explanation of synthesizer voices.) + * Obtains the current status of the voices produced by this synthesizer. If + * this class of {@code Synthesizer} does not provide voice information, the + * returned array will always be of length 0. Otherwise, its length is + * always equal to the total number of voices, as returned by + * {@code getMaxPolyphony()}. (See the {@code VoiceStatus} class description + * for an explanation of synthesizer voices.) * - * @return an array of VoiceStatus objects that supply - * information about the corresponding synthesizer voices + * @return an array of {@code VoiceStatus} objects that supply information + * about the corresponding synthesizer voices * @see #getMaxPolyphony * @see VoiceStatus */ - public VoiceStatus[] getVoiceStatus(); - + VoiceStatus[] getVoiceStatus(); /** * Informs the caller whether this synthesizer is capable of loading - * instruments from the specified soundbank. - * If the soundbank is unsupported, any attempts to load instruments from - * it will result in an IllegalArgumentException. - * @param soundbank soundbank for which support is queried - * @return true if the soundbank is supported, otherwise false + * instruments from the specified soundbank. If the soundbank is + * unsupported, any attempts to load instruments from it will result in an + * {@code IllegalArgumentException}. + * + * @param soundbank soundbank for which support is queried + * @return {@code true} if the soundbank is supported, otherwise + * {@code false} * @see #loadInstruments * @see #loadAllInstruments * @see #unloadInstruments * @see #unloadAllInstruments * @see #getDefaultSoundbank */ - public boolean isSoundbankSupported(Soundbank soundbank); - + boolean isSoundbankSupported(Soundbank soundbank); /** - * Makes a particular instrument available for synthesis. This instrument - * is loaded into the patch location specified by its Patch - * object, so that if a program-change message is - * received (or has been received) that causes that patch to be selected, - * subsequent notes will be played using the sound of - * instrument. If the specified instrument is already loaded, - * this method does nothing and returns true. + * Makes a particular instrument available for synthesis. This instrument is + * loaded into the patch location specified by its {@code Patch} object, so + * that if a program-change message is received (or has been received) that + * causes that patch to be selected, subsequent notes will be played using + * the sound of {@code instrument}. If the specified instrument is already + * loaded, this method does nothing and returns {@code true}. *

    - * The instrument must be part of a soundbank - * that this Synthesizer supports. (To make sure, you can use - * the getSoundbank method of Instrument and the - * isSoundbankSupported method of Synthesizer.) - * @param instrument instrument to load - * @return true if the instrument is successfully loaded (or - * already had been), false if the instrument could not be - * loaded (for example, if the synthesizer has insufficient - * memory to load it) - * @throws IllegalArgumentException if this - * Synthesizer doesn't support the specified instrument's - * soundbank + * The instrument must be part of a soundbank that this {@code Synthesizer} + * supports. (To make sure, you can use the {@code getSoundbank} method of + * {@code Instrument} and the {@code isSoundbankSupported} method of + * {@code Synthesizer}.) + * + * @param instrument instrument to load + * @return {@code true} if the instrument is successfully loaded (or already + * had been), {@code false} if the instrument could not be loaded + * (for example, if the synthesizer has insufficient memory to load + * it) + * @throws IllegalArgumentException if this {@code Synthesizer} doesn't + * support the specified instrument's soundbank * @see #unloadInstrument * @see #loadInstruments * @see #loadAllInstruments @@ -180,138 +173,139 @@ public interface Synthesizer extends MidiDevice { * @see SoundbankResource#getSoundbank * @see MidiChannel#programChange(int, int) */ - public boolean loadInstrument(Instrument instrument); - + boolean loadInstrument(Instrument instrument); /** * Unloads a particular instrument. - * @param instrument instrument to unload - * @throws IllegalArgumentException if this - * Synthesizer doesn't support the specified instrument's - * soundbank + * + * @param instrument instrument to unload + * @throws IllegalArgumentException if this {@code Synthesizer} doesn't + * support the specified instrument's soundbank * @see #loadInstrument * @see #unloadInstruments * @see #unloadAllInstruments * @see #getLoadedInstruments * @see #remapInstrument */ - public void unloadInstrument(Instrument instrument); - + void unloadInstrument(Instrument instrument); /** - * Remaps an instrument. Instrument to takes the - * place of instrument from.
    - * For example, if from was located at bank number 2, - * program number 11, remapping causes that bank and program location - * to be occupied instead by to.
    - * If the function succeeds, instrument from is unloaded. - *

    To cancel the remapping reload instrument from by - * invoking one of {@link #loadInstrument}, {@link #loadInstruments} - * or {@link #loadAllInstruments}. + * Remaps an instrument. Instrument {@code to} takes the place of instrument + * {@code from}. + *
    + * For example, if {@code from} was located at bank number 2, program number + * 11, remapping causes that bank and program location to be occupied + * instead by {@code to}. + *
    + * If the function succeeds, instrument {@code from} is unloaded. + *

    + * To cancel the remapping reload instrument {@code from} by invoking one of + * {@link #loadInstrument}, {@link #loadInstruments} or + * {@link #loadAllInstruments}. * - * @param from the Instrument object to be replaced - * @param to the Instrument object to be used in place - * of the old instrument, it should be loaded into the synthesizer - * @return true if the instrument successfully remapped, - * false if feature is not implemented by synthesizer - * @throws IllegalArgumentException if instrument - * from or instrument to aren't supported by - * synthesizer or if instrument to is not loaded - * @throws NullPointerException if from or - * to parameters have null value + * @param from the {@code Instrument} object to be replaced + * @param to the {@code Instrument} object to be used in place of the old + * instrument, it should be loaded into the synthesizer + * @return {@code true} if the instrument successfully remapped, + * {@code false} if feature is not implemented by synthesizer + * @throws IllegalArgumentException if instrument {@code from} or instrument + * {@code to} aren't supported by synthesizer or if instrument + * {@code to} is not loaded + * @throws NullPointerException if {@code from} or {@code to} parameters + * have null value * @see #loadInstrument * @see #loadInstruments * @see #loadAllInstruments */ - public boolean remapInstrument(Instrument from, Instrument to); - + boolean remapInstrument(Instrument from, Instrument to); /** - * Obtains the default soundbank for the synthesizer, if one exists. - * (Some synthesizers provide a default or built-in soundbank.) - * If a synthesizer doesn't have a default soundbank, instruments must - * be loaded explicitly from an external soundbank. - * @return default soundbank, or null if one does not exist. + * Obtains the default soundbank for the synthesizer, if one exists. (Some + * synthesizers provide a default or built-in soundbank.) If a synthesizer + * doesn't have a default soundbank, instruments must be loaded explicitly + * from an external soundbank. + * + * @return default soundbank, or {@code null} if one does not exist * @see #isSoundbankSupported */ - public Soundbank getDefaultSoundbank(); - + Soundbank getDefaultSoundbank(); /** - * Obtains a list of instruments that come with the synthesizer. These - * instruments might be built into the synthesizer, or they might be - * part of a default soundbank provided with the synthesizer, etc. + * Obtains a list of instruments that come with the synthesizer. These + * instruments might be built into the synthesizer, or they might be part of + * a default soundbank provided with the synthesizer, etc. *

    - * Note that you don't use this method to find out which instruments are + * Note that you don't use this method to find out which instruments are * currently loaded onto the synthesizer; for that purpose, you use - * getLoadedInstruments(). - * Nor does the method indicate all the instruments that can be loaded onto - * the synthesizer; it only indicates the subset that come with the synthesizer. - * To learn whether another instrument can be loaded, you can invoke - * isSoundbankSupported(), and if the instrument's - * Soundbank is supported, you can try loading the instrument. + * {@code getLoadedInstruments()}. Nor does the method indicate all the + * instruments that can be loaded onto the synthesizer; it only indicates + * the subset that come with the synthesizer. To learn whether another + * instrument can be loaded, you can invoke {@code isSoundbankSupported()}, + * and if the instrument's {@code Soundbank} is supported, you can try + * loading the instrument. * - * @return list of available instruments. If the synthesizer - * has no instruments coming with it, an array of length 0 is returned. + * @return list of available instruments. If the synthesizer has no + * instruments coming with it, an array of length 0 is returned. * @see #getLoadedInstruments * @see #isSoundbankSupported(Soundbank) * @see #loadInstrument */ - public Instrument[] getAvailableInstruments(); - + Instrument[] getAvailableInstruments(); /** * Obtains a list of the instruments that are currently loaded onto this - * Synthesizer. + * {@code Synthesizer}. + * * @return a list of currently loaded instruments * @see #loadInstrument * @see #getAvailableInstruments * @see Soundbank#getInstruments */ - public Instrument[] getLoadedInstruments(); - + Instrument[] getLoadedInstruments(); /** - * Loads onto the Synthesizer all instruments contained - * in the specified Soundbank. - * @param soundbank the Soundbank whose are instruments are - * to be loaded - * @return true if the instruments are all successfully loaded (or - * already had been), false if any instrument could not be - * loaded (for example, if the Synthesizer had insufficient memory) + * Loads onto the {@code Synthesizer} all instruments contained in the + * specified {@code Soundbank}. + * + * @param soundbank the {@code Soundbank} whose are instruments are to be + * loaded + * @return {@code true} if the instruments are all successfully loaded (or + * already had been), {@code false} if any instrument could not be + * loaded (for example, if the {@code Synthesizer} had insufficient + * memory) * @throws IllegalArgumentException if the requested soundbank is - * incompatible with this synthesizer. + * incompatible with this synthesizer * @see #isSoundbankSupported * @see #loadInstrument * @see #loadInstruments */ - public boolean loadAllInstruments(Soundbank soundbank); - - + boolean loadAllInstruments(Soundbank soundbank); /** - * Unloads all instruments contained in the specified Soundbank. - * @param soundbank soundbank containing instruments to unload - * @throws IllegalArgumentException thrown if the soundbank is not supported. + * Unloads all instruments contained in the specified {@code Soundbank}. + * + * @param soundbank soundbank containing instruments to unload + * @throws IllegalArgumentException thrown if the soundbank is not supported * @see #isSoundbankSupported * @see #unloadInstrument * @see #unloadInstruments */ - public void unloadAllInstruments(Soundbank soundbank); - + void unloadAllInstruments(Soundbank soundbank); /** * Loads the instruments referenced by the specified patches, from the - * specified Soundbank. Each of the Patch objects - * indicates a bank and program number; the Instrument that - * has the matching Patch is loaded into that bank and program - * location. - * @param soundbank the Soundbank containing the instruments to load - * @param patchList list of patches for which instruments should be loaded - * @return true if the instruments are all successfully loaded (or - * already had been), false if any instrument could not be - * loaded (for example, if the Synthesizer had insufficient memory) - * @throws IllegalArgumentException thrown if the soundbank is not supported. + * specified {@code Soundbank}. Each of the {@code Patch} objects indicates + * a bank and program number; the {@code Instrument} that has the matching + * {@code Patch} is loaded into that bank and program location. + * + * @param soundbank the {@code Soundbank} containing the instruments to + * load + * @param patchList list of patches for which instruments should be loaded + * @return {@code true} if the instruments are all successfully loaded (or + * already had been), {@code false} if any instrument could not be + * loaded (for example, if the {@code Synthesizer} had insufficient + * memory) + * @throws IllegalArgumentException thrown if the soundbank is not supported * @see #isSoundbankSupported * @see Instrument#getPatch * @see #loadAllInstruments @@ -319,76 +313,76 @@ public interface Synthesizer extends MidiDevice { * @see Soundbank#getInstrument(Patch) * @see Sequence#getPatchList() */ - public boolean loadInstruments(Soundbank soundbank, Patch[] patchList); + boolean loadInstruments(Soundbank soundbank, Patch[] patchList); /** - * Unloads the instruments referenced by the specified patches, from the MIDI sound bank specified. - * @param soundbank soundbank containing instruments to unload - * @param patchList list of patches for which instruments should be unloaded - * @throws IllegalArgumentException thrown if the soundbank is not supported. + * Unloads the instruments referenced by the specified patches, from the + * MIDI sound bank specified. * + * @param soundbank soundbank containing instruments to unload + * @param patchList list of patches for which instruments should be + * unloaded + * @throws IllegalArgumentException thrown if the soundbank is not supported * @see #unloadInstrument * @see #unloadAllInstruments * @see #isSoundbankSupported * @see Instrument#getPatch * @see #loadInstruments */ - public void unloadInstruments(Soundbank soundbank, Patch[] patchList); - + void unloadInstruments(Soundbank soundbank, Patch[] patchList); // RECEIVER METHODS /** * Obtains the name of the receiver. + * * @return receiver name */ - // public abstract String getName(); - + // abstract String getName(); /** * Opens the receiver. + * * @throws MidiUnavailableException if the receiver is cannot be opened, - * usually because the MIDI device is in use by another application. - * @throws SecurityException if the receiver cannot be opened due to security - * restrictions. + * usually because the MIDI device is in use by another application. + * @throws SecurityException if the receiver cannot be opened due to + * security restrictions */ - // public abstract void open() throws MidiUnavailableException, SecurityException; - + // abstract void open() throws MidiUnavailableException, SecurityException; /** * Closes the receiver. */ - // public abstract void close(); - + // abstract void close(); /** * Sends a MIDI event to the receiver. - * @param event event to send. - * @throws IllegalStateException if the receiver is not open. + * + * @param event event to send + * @throws IllegalStateException if the receiver is not open */ - // public void send(MidiEvent event) throws IllegalStateException { + // void send(MidiEvent event) throws IllegalStateException { // // } - /** - * Obtains the set of controls supported by the - * element. If no controls are supported, returns an - * array of length 0. + * Obtains the set of controls supported by the element. If no controls are + * supported, returns an array of length 0. + * * @return set of controls */ // $$kk: 03.04.99: josh bloch recommends getting rid of this: // what can you really do with a set of untyped controls?? - // $$kk: 03.05.99: i am putting this back in. for one thing, + // $$kk: 03.05.99: i am putting this back in. for one thing, // you can check the length and know whether you should keep // looking.... - // public Control[] getControls(); + // Control[] getControls(); /** * Obtains the specified control. - * @param controlClass class of the requested control - * @return requested control object, or null if the - * control is not supported. + * + * @param controlClass class of the requested control + * @return requested control object, or null if the control is not supported */ - // public Control getControl(Class controlClass); + // Control getControl(Class controlClass); } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/SysexMessage.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/SysexMessage.java index ae4e418e8e6..8bcd00a9030 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/SysexMessage.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/SysexMessage.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -26,47 +26,47 @@ package javax.sound.midi; /** - * A SysexMessage object represents a MIDI system exclusive message. + * A {@code SysexMessage} object represents a MIDI system exclusive message. *

    - * When a system exclusive message is read from a MIDI file, it always has - * a defined length. Data from a system exclusive message from a MIDI file - * should be stored in the data array of a SysexMessage as - * follows: the system exclusive message status byte (0xF0 or 0xF7), all - * message data bytes, and finally the end-of-exclusive flag (0xF7). - * The length reported by the SysexMessage object is therefore - * the length of the system exclusive data plus two: one byte for the status - * byte and one for the end-of-exclusive flag. + * When a system exclusive message is read from a MIDI file, it always has a + * defined length. Data from a system exclusive message from a MIDI file should + * be stored in the data array of a {@code SysexMessage} as follows: the system + * exclusive message status byte (0xF0 or 0xF7), all message data bytes, and + * finally the end-of-exclusive flag (0xF7). The length reported by the + * {@code SysexMessage} object is therefore the length of the system exclusive + * data plus two: one byte for the status byte and one for the end-of-exclusive + * flag. *

    - * As dictated by the Standard MIDI Files specification, two status byte values are legal - * for a SysexMessage read from a MIDI file: + * As dictated by the Standard MIDI Files specification, two status byte values + * are legal for a {@code SysexMessage} read from a MIDI file: *

      *
    • 0xF0: System Exclusive message (same as in MIDI wire protocol)
    • *
    • 0xF7: Special System Exclusive message
    • *
    - *

    - * When Java Sound is used to handle system exclusive data that is being received - * using MIDI wire protocol, it should place the data in one or more - * SysexMessages. In this case, the length of the system exclusive data + * When Java Sound is used to handle system exclusive data that is being + * received using MIDI wire protocol, it should place the data in one or more + * {@code SysexMessages}. In this case, the length of the system exclusive data * is not known in advance; the end of the system exclusive data is marked by an * end-of-exclusive flag (0xF7) in the MIDI wire byte stream. *

      *
    • 0xF0: System Exclusive message (same as in MIDI wire protocol)
    • *
    • 0xF7: End of Exclusive (EOX)
    • *
    - * The first SysexMessage object containing data for a particular system - * exclusive message should have the status value 0xF0. If this message contains all - * the system exclusive data - * for the message, it should end with the status byte 0xF7 (EOX). - * Otherwise, additional system exclusive data should be sent in one or more - * SysexMessages with a status value of 0xF7. The SysexMessage - * containing the last of the data for the system exclusive message should end with the - * value 0xF7 (EOX) to mark the end of the system exclusive message. + * The first {@code SysexMessage} object containing data for a particular system + * exclusive message should have the status value 0xF0. If this message contains + * all the system exclusive data for the message, it should end with the status + * byte 0xF7 (EOX). Otherwise, additional system exclusive data should be sent + * in one or more {@code SysexMessages} with a status value of 0xF7. The + * {@code SysexMessage} containing the last of the data for the system exclusive + * message should end with the value 0xF7 (EOX) to mark the end of the system + * exclusive message. *

    - * If system exclusive data from SysexMessages objects is being transmitted - * using MIDI wire protocol, only the initial 0xF0 status byte, the system exclusive - * data itself, and the final 0xF7 (EOX) byte should be propagated; any 0xF7 status - * bytes used to indicate that a SysexMessage contains continuing system - * exclusive data should not be propagated via MIDI wire protocol. + * If system exclusive data from {@code SysexMessages} objects is being + * transmitted using MIDI wire protocol, only the initial 0xF0 status byte, the + * system exclusive data itself, and the final 0xF7 (EOX) byte should be + * propagated; any 0xF7 status bytes used to indicate that a + * {@code SysexMessage} contains continuing system exclusive data should not be + * propagated via MIDI wire protocol. * * @author David Rivas * @author Kara Kytle @@ -74,43 +74,36 @@ package javax.sound.midi; */ public class SysexMessage extends MidiMessage { - // Status byte defines - /** * Status byte for System Exclusive message (0xF0, or 240). + * * @see MidiMessage#getStatus */ public static final int SYSTEM_EXCLUSIVE = 0xF0; // 240 - /** - * Status byte for Special System Exclusive message (0xF7, or 247), which is used - * in MIDI files. It has the same value as END_OF_EXCLUSIVE, which - * is used in the real-time "MIDI wire" protocol. + * Status byte for Special System Exclusive message (0xF7, or 247), which is + * used in MIDI files. It has the same value as END_OF_EXCLUSIVE, which is + * used in the real-time "MIDI wire" protocol. + * * @see MidiMessage#getStatus */ public static final int SPECIAL_SYSTEM_EXCLUSIVE = 0xF7; // 247 - - // Instance variables - - - /* - * The data bytes for this system exclusive message. These are - * initialized to null and are set explicitly - * by {@link #setMessage(int, byte[], int, long) setMessage}. + /** + * The data bytes for this system exclusive message. These are initialized + * to {@code null} and are set explicitly by + * {@link #setMessage(int, byte[], int, long) setMessage}. */ //protected byte[] data = null; - /** - * Constructs a new SysexMessage. The - * contents of the new message are guaranteed to specify - * a valid MIDI message. Subsequently, you may set the - * contents of the message using one of the setMessage - * methods. + * Constructs a new {@code SysexMessage}. The contents of the new message + * are guaranteed to specify a valid MIDI message. Subsequently, you may set + * the contents of the message using one of the {@code setMessage} methods. + * * @see #setMessage */ public SysexMessage() { @@ -121,18 +114,17 @@ public class SysexMessage extends MidiMessage { } /** - * Constructs a new {@code SysexMessage} and sets the data for - * the message. The first byte of the data array must be a valid system - * exclusive status byte (0xF0 or 0xF7). - * The contents of the message can be changed by using one of - * the {@code setMessage} methods. + * Constructs a new {@code SysexMessage} and sets the data for the message. + * The first byte of the data array must be a valid system exclusive status + * byte (0xF0 or 0xF7). The contents of the message can be changed by using + * one of the {@code setMessage} methods. * - * @param data the system exclusive message data including the status byte - * @param length the length of the valid message data in the array, - * including the status byte; it should be non-negative and less than - * or equal to {@code data.length} - * @throws InvalidMidiDataException if the parameter values - * do not specify a valid MIDI meta message. + * @param data the system exclusive message data including the status byte + * @param length the length of the valid message data in the array, + * including the status byte; it should be non-negative and less + * than or equal to {@code data.length} + * @throws InvalidMidiDataException if the parameter values do not specify a + * valid MIDI meta message. * @see #setMessage(byte[], int) * @see #setMessage(int, byte[], int) * @see #getData() @@ -146,17 +138,17 @@ public class SysexMessage extends MidiMessage { /** * Constructs a new {@code SysexMessage} and sets the data for the message. - * The contents of the message can be changed by using one of - * the {@code setMessage} methods. + * The contents of the message can be changed by using one of the + * {@code setMessage} methods. * - * @param status the status byte for the message; it must be a valid system - * exclusive status byte (0xF0 or 0xF7) - * @param data the system exclusive message data (without the status byte) - * @param length the length of the valid message data in the array; - * it should be non-negative and less than or equal to - * {@code data.length} - * @throws InvalidMidiDataException if the parameter values - * do not specify a valid MIDI meta message. + * @param status the status byte for the message; it must be a valid system + * exclusive status byte (0xF0 or 0xF7) + * @param data the system exclusive message data (without the status byte) + * @param length the length of the valid message data in the array; it + * should be non-negative and less than or equal to + * {@code data.length} + * @throws InvalidMidiDataException if the parameter values do not specify a + * valid MIDI meta message * @see #setMessage(byte[], int) * @see #setMessage(int, byte[], int) * @see #getData() @@ -168,26 +160,24 @@ public class SysexMessage extends MidiMessage { setMessage(status, data, length); } - /** - * Constructs a new SysexMessage. - * @param data an array of bytes containing the complete message. - * The message data may be changed using the setMessage - * method. + * Constructs a new {@code SysexMessage}. + * + * @param data an array of bytes containing the complete message. The + * message data may be changed using the {@code setMessage} method. * @see #setMessage */ protected SysexMessage(byte[] data) { super(data); } - /** - * Sets the data for the system exclusive message. The - * first byte of the data array must be a valid system - * exclusive status byte (0xF0 or 0xF7). - * @param data the system exclusive message data - * @param length the length of the valid message data in - * the array, including the status byte. + * Sets the data for the system exclusive message. The first byte of the + * data array must be a valid system exclusive status byte (0xF0 or 0xF7). + * + * @param data the system exclusive message data + * @param length the length of the valid message data in the array, + * including the status byte */ public void setMessage(byte[] data, int length) throws InvalidMidiDataException { int status = (data[0] & 0xFF); @@ -197,14 +187,14 @@ public class SysexMessage extends MidiMessage { super.setMessage(data, length); } - /** * Sets the data for the system exclusive message. - * @param status the status byte for the message (0xF0 or 0xF7) - * @param data the system exclusive message data - * @param length the length of the valid message data in - * the array - * @throws InvalidMidiDataException if the status byte is invalid for a sysex message + * + * @param status the status byte for the message (0xF0 or 0xF7) + * @param data the system exclusive message data + * @param length the length of the valid message data in the array + * @throws InvalidMidiDataException if the status byte is invalid for a + * sysex message */ public void setMessage(int status, byte[] data, int length) throws InvalidMidiDataException { if ( (status != 0xF0) && (status != 0xF7) ) { @@ -225,11 +215,11 @@ public class SysexMessage extends MidiMessage { } } - /** - * Obtains a copy of the data for the system exclusive message. - * The returned array of bytes does not include the status byte. - * @return array containing the system exclusive message data. + * Obtains a copy of the data for the system exclusive message. The returned + * array of bytes does not include the status byte. + * + * @return array containing the system exclusive message data */ public byte[] getData() { byte[] returnedArray = new byte[length - 1]; @@ -237,10 +227,10 @@ public class SysexMessage extends MidiMessage { return returnedArray; } - /** - * Creates a new object of the same class and with the same contents - * as this object. + * Creates a new object of the same class and with the same contents as this + * object. + * * @return a clone of this instance */ public Object clone() { diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/Track.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/Track.java index d9e0f438b6c..95a42c7f703 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/Track.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/Track.java @@ -25,41 +25,40 @@ package javax.sound.midi; -import java.util.Vector; import java.util.ArrayList; import java.util.HashSet; + import com.sun.media.sound.MidiUtils; /** - * A MIDI track is an independent stream of MIDI events (time-stamped MIDI - * data) that can be stored along with other tracks in a standard MIDI file. - * The MIDI specification allows only 16 channels of MIDI data, but tracks - * are a way to get around this limitation. A MIDI file can contain any number - * of tracks, each containing its own stream of up to 16 channels of MIDI data. + * A MIDI track is an independent stream of MIDI events (time-stamped MIDI data) + * that can be stored along with other tracks in a standard MIDI file. The MIDI + * specification allows only 16 channels of MIDI data, but tracks are a way to + * get around this limitation. A MIDI file can contain any number of tracks, + * each containing its own stream of up to 16 channels of MIDI data. *

    - * A Track occupies a middle level in the hierarchy of data played - * by a {@link Sequencer}: sequencers play sequences, which contain tracks, - * which contain MIDI events. A sequencer may provide controls that mute - * or solo individual tracks. + * A {@code Track} occupies a middle level in the hierarchy of data played by a + * {@link Sequencer}: sequencers play sequences, which contain tracks, which + * contain MIDI events. A sequencer may provide controls that mute or solo + * individual tracks. *

    * The timing information and resolution for a track is controlled by and stored - * in the sequence containing the track. A given Track - * is considered to belong to the particular {@link Sequence} that - * maintains its timing. For this reason, a new (empty) track is created by calling the - * {@link Sequence#createTrack} method, rather than by directly invoking a - * Track constructor. + * in the sequence containing the track. A given {@code Track} is considered to + * belong to the particular {@link Sequence} that maintains its timing. For this + * reason, a new (empty) track is created by calling the + * {@link Sequence#createTrack} method, rather than by directly invoking a + * {@code Track} constructor. *

    - * The Track class provides methods to edit the track by adding - * or removing MidiEvent objects from it. These operations keep - * the event list in the correct time order. Methods are also - * included to obtain the track's size, in terms of either the number of events - * it contains or its duration in ticks. - * - * @see Sequencer#setTrackMute - * @see Sequencer#setTrackSolo + * The {@code Track} class provides methods to edit the track by adding or + * removing {@code MidiEvent} objects from it. These operations keep the event + * list in the correct time order. Methods are also included to obtain the + * track's size, in terms of either the number of events it contains or its + * duration in ticks. * * @author Kara Kytle * @author Florian Bomers + * @see Sequencer#setTrackMute + * @see Sequencer#setTrackSolo */ public class Track { @@ -73,10 +72,9 @@ public class Track { private MidiEvent eotEvent; - /** - * Package-private constructor. Constructs a new, empty Track object, - * which initially contains one event, the meta-event End of Track. + * Package-private constructor. Constructs a new, empty Track object, which + * initially contains one event, the meta-event End of Track. */ Track() { // start with the end of track event @@ -87,14 +85,14 @@ public class Track { } /** - * Adds a new event to the track. However, if the event is already - * contained in the track, it is not added again. The list of events - * is kept in time order, meaning that this event inserted at the - * appropriate place in the list, not necessarily at the end. + * Adds a new event to the track. However, if the event is already contained + * in the track, it is not added again. The list of events is kept in time + * order, meaning that this event inserted at the appropriate place in the + * list, not necessarily at the end. * - * @param event the event to add - * @return true if the event did not already exist in the - * track and was added, otherwise false + * @param event the event to add + * @return {@code true} if the event did not already exist in the track and + * was added, otherwise {@code false} */ public boolean add(MidiEvent event) { if (event == null) { @@ -176,12 +174,12 @@ public class Track { return false; } - /** * Removes the specified event from the track. - * @param event the event to remove - * @return true if the event existed in the track and was removed, - * otherwise false + * + * @param event the event to remove + * @return {@code true} if the event existed in the track and was removed, + * otherwise {@code false} */ public boolean remove(MidiEvent event) { @@ -207,15 +205,14 @@ public class Track { return false; } - /** * Obtains the event at the specified index. - * @param index the location of the desired event in the event vector - * @throws ArrayIndexOutOfBoundsException if the - * specified index is negative or not less than the current size of - * this track. - * @see #size + * + * @param index the location of the desired event in the event vector * @return the event at the specified index + * @throws ArrayIndexOutOfBoundsException if the specified index is negative + * or not less than the current size of this track + * @see #size */ public MidiEvent get(int index) throws ArrayIndexOutOfBoundsException { try { @@ -227,9 +224,9 @@ public class Track { } } - /** * Obtains the number of events in this track. + * * @return the size of the track's event vector */ public int size() { @@ -238,12 +235,12 @@ public class Track { } } - /** - * Obtains the length of the track, expressed in MIDI ticks. (The - * duration of a tick in seconds is determined by the timing resolution - * of the Sequence containing this track, and also by - * the tempo of the music as set by the sequencer.) + * Obtains the length of the track, expressed in MIDI ticks. (The duration + * of a tick in seconds is determined by the timing resolution of the + * {@code Sequence} containing this track, and also by the tempo of the + * music as set by the sequencer.) + * * @return the duration, in ticks * @see Sequence#Sequence(float, int) * @see Sequencer#setTempoInBPM(float) @@ -271,5 +268,4 @@ public class Track { throw new InvalidMidiDataException("cannot modify end of track message"); } } - } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/Transmitter.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/Transmitter.java index e78b800c728..639aa2c750d 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/Transmitter.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/Transmitter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2014, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,52 +25,49 @@ package javax.sound.midi; - /** - * A Transmitter sends {@link MidiEvent} objects to one or more - * {@link Receiver Receivers}. Common MIDI transmitters include sequencers - * and MIDI input ports. - * - * @see Receiver + * A {@code Transmitter} sends {@link MidiEvent} objects to one or more + * {@link Receiver Receivers}. Common MIDI transmitters include sequencers and + * MIDI input ports. * * @author Kara Kytle + * @see Receiver */ public interface Transmitter extends AutoCloseable { - /** * Sets the receiver to which this transmitter will deliver MIDI messages. * If a receiver is currently set, it is replaced with this one. - * @param receiver the desired receiver. + * + * @param receiver the desired receiver */ - public void setReceiver(Receiver receiver); - + void setReceiver(Receiver receiver); /** - * Obtains the current receiver to which this transmitter will deliver MIDI messages. - * @return the current receiver. If no receiver is currently set, - * returns null + * Obtains the current receiver to which this transmitter will deliver MIDI + * messages. + * + * @return the current receiver. If no receiver is currently set, returns + * {@code null}. */ - public Receiver getReceiver(); - + Receiver getReceiver(); /** * Indicates that the application has finished using the transmitter, and * that limited resources it requires may be released or made available. - * - *

    If the creation of this Transmitter resulted in - * implicitly opening the underlying device, the device is - * implicitly closed by this method. This is true unless the device is - * kept open by other Receiver or Transmitter - * instances that opened the device implicitly, and unless the device - * has been opened explicitly. If the device this - * Transmitter is retrieved from is closed explicitly - * by calling {@link MidiDevice#close MidiDevice.close}, the - * Transmitter is closed, too. For a detailed - * description of open/close behaviour see the class description - * of {@link javax.sound.midi.MidiDevice MidiDevice}. + *

    + * If the creation of this {@code Transmitter} resulted in implicitly + * opening the underlying device, the device is implicitly closed by this + * method. This is true unless the device is kept open by other + * {@code Receiver} or {@code Transmitter} instances that opened the device + * implicitly, and unless the device has been opened explicitly. If the + * device this {@code Transmitter} is retrieved from is closed explicitly by + * calling {@link MidiDevice#close MidiDevice.close}, the + * {@code Transmitter} is closed, too. For a detailed description of + * open/close behaviour see the class description of + * {@link MidiDevice MidiDevice}. * * @see javax.sound.midi.MidiSystem#getTransmitter */ - public void close(); + void close(); } diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/VoiceStatus.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/VoiceStatus.java index 45f2e4d964c..2d679613e01 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/VoiceStatus.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/VoiceStatus.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2002, Oracle and/or its affiliates. All rights reserved. + * 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 @@ -25,93 +25,83 @@ package javax.sound.midi; - /** - * A VoiceStatus object contains information about the current - * status of one of the voices produced by a {@link Synthesizer}. + * A {@code VoiceStatus} object contains information about the current status of + * one of the voices produced by a {@link Synthesizer}. *

    * MIDI synthesizers are generally capable of producing some maximum number of - * simultaneous notes, also referred to as voices. A voice is a stream - * of successive single notes, and the process of assigning incoming MIDI notes to - * specific voices is known as voice allocation. - * However, the voice-allocation algorithm and the contents of each voice are - * normally internal to a MIDI synthesizer and hidden from outside view. One can, of - * course, learn from MIDI messages which notes the synthesizer is playing, and - * one might be able deduce something about the assignment of notes to voices. - * But MIDI itself does not provide a means to report which notes a - * synthesizer has assigned to which voice, nor even to report how many voices - * the synthesizer is capable of synthesizing. + * simultaneous notes, also referred to as voices. A voice is a stream of + * successive single notes, and the process of assigning incoming MIDI notes to + * specific voices is known as voice allocation. However, the voice-allocation + * algorithm and the contents of each voice are normally internal to a MIDI + * synthesizer and hidden from outside view. One can, of course, learn from MIDI + * messages which notes the synthesizer is playing, and one might be able deduce + * something about the assignment of notes to voices. But MIDI itself does not + * provide a means to report which notes a synthesizer has assigned to which + * voice, nor even to report how many voices the synthesizer is capable of + * synthesizing. *

    - * In Java Sound, however, a - * Synthesizer class can expose the contents of its voices through its - * {@link Synthesizer#getVoiceStatus() getVoiceStatus()} method. - * This behavior is recommended but optional; - * synthesizers that don't expose their voice allocation simply return a - * zero-length array. A Synthesizer that does report its voice status - * should maintain this information at - * all times for all of its voices, whether they are currently sounding or - * not. In other words, a given type of Synthesizer always has a fixed - * number of voices, equal to the maximum number of simultaneous notes it is - * capable of sounding. + * In Java Sound, however, a {@code Synthesizer} class can expose the contents + * of its voices through its + * {@link Synthesizer#getVoiceStatus() getVoiceStatus()} method. This behavior + * is recommended but optional; synthesizers that don't expose their voice + * allocation simply return a zero-length array. A {@code Synthesizer} that does + * report its voice status should maintain this information at all times for all + * of its voices, whether they are currently sounding or not. In other words, a + * given type of {@code Synthesizer} always has a fixed number of voices, equal + * to the maximum number of simultaneous notes it is capable of sounding. *

    - * - * If the voice is not currently processing a MIDI note, it - * is considered inactive. A voice is inactive when it has - * been given no note-on commands, or when every note-on command received has - * been terminated by a corresponding note-off (or by an "all notes off" - * message). For example, this happens when a synthesizer capable of playing 16 - * simultaneous notes is told to play a four-note chord; only - * four voices are active in this case (assuming no earlier notes are still playing). - * Usually, a voice whose status is reported as active is producing audible sound, but this - * is not always true; it depends on the details of the instrument (that - * is, the synthesis algorithm) and how long the note has been going on. - * For example, a voice may be synthesizing the sound of a single hand-clap. Because - * this sound dies away so quickly, it may become inaudible before a note-off - * message is received. In such a situation, the voice is still considered active - * even though no sound is currently being produced. + * If the voice is not currently processing + * a MIDI note, it is considered inactive. A voice is inactive when it has been + * given no note-on commands, or when every note-on command received has been + * terminated by a corresponding note-off (or by an "all notes off" message). + * For example, this happens when a synthesizer capable of playing 16 + * simultaneous notes is told to play a four-note chord; only four voices are + * active in this case (assuming no earlier notes are still playing). Usually, a + * voice whose status is reported as active is producing audible sound, but this + * is not always true; it depends on the details of the instrument (that is, the + * synthesis algorithm) and how long the note has been going on. For example, a + * voice may be synthesizing the sound of a single hand-clap. Because this sound + * dies away so quickly, it may become inaudible before a note-off message is + * received. In such a situation, the voice is still considered active even + * though no sound is currently being produced. *

    - * Besides its active or inactive status, the VoiceStatus class - * provides fields that reveal the voice's current MIDI channel, bank and - * program number, MIDI note number, and MIDI volume. All of these can - * change during the course of a voice. While the voice is inactive, each - * of these fields has an unspecified value, so you should check the active - * field first. - * - * @see Synthesizer#getMaxPolyphony - * @see Synthesizer#getVoiceStatus + * Besides its active or inactive status, the {@code VoiceStatus} class provides + * fields that reveal the voice's current MIDI channel, bank and program number, + * MIDI note number, and MIDI volume. All of these can change during the course + * of a voice. While the voice is inactive, each of these fields has an + * unspecified value, so you should check the active field first. * * @author David Rivas * @author Kara Kytle + * @see Synthesizer#getMaxPolyphony + * @see Synthesizer#getVoiceStatus */ - public class VoiceStatus { - /** - * Indicates whether the voice is currently processing a MIDI note. - * See the explanation of - * active and inactive voices. + * Indicates whether the voice is currently processing a MIDI note. See the + * explanation of + * active and inactive voices. */ public boolean active = false; - /** - * The MIDI channel on which this voice is playing. The value is a - * zero-based channel number if the voice is active, or - * unspecified if the voice is inactive. + * The MIDI channel on which this voice is playing. The value is a + * zero-based channel number if the voice is active, or unspecified if the + * voice is inactive. * * @see MidiChannel * @see #active */ public int channel = 0; - /** * The bank number of the instrument that this voice is currently using. * This is a number dictated by the MIDI bank-select message; it does not - * refer to a SoundBank object. - * The value ranges from 0 to 16383 if the voice is active, and is - * unspecified if the voice is inactive. + * refer to a {@code SoundBank} object. The value ranges from 0 to 16383 if + * the voice is active, and is unspecified if the voice is inactive. + * * @see Patch * @see Soundbank * @see #active @@ -119,11 +109,10 @@ public class VoiceStatus { */ public int bank = 0; - /** * The program number of the instrument that this voice is currently using. - * The value ranges from 0 to 127 if the voice is active, and is - * unspecified if the voice is inactive. + * The value ranges from 0 to 127 if the voice is active, and is unspecified + * if the voice is inactive. * * @see MidiChannel#getProgram * @see Patch @@ -131,28 +120,24 @@ public class VoiceStatus { */ public int program = 0; - /** - * The MIDI note that this voice is playing. The range for an active voice - * is from 0 to 127 in semitones, with 60 referring to Middle C. - * The value is unspecified if the voice is inactive. + * The MIDI note that this voice is playing. The range for an active voice + * is from 0 to 127 in semitones, with 60 referring to Middle C. The value + * is unspecified if the voice is inactive. * * @see MidiChannel#noteOn * @see #active */ public int note = 0; - /** - * The current MIDI volume level for the voice. - * The value ranges from 0 to 127 if the voice is active, and is - * unspecified if the voice is inactive. + * The current MIDI volume level for the voice. The value ranges from 0 to + * 127 if the voice is active, and is unspecified if the voice is inactive. *

    - * Note that this value does not necessarily reflect - * the instantaneous level of the sound produced by this - * voice; that level is the result of many contributing - * factors, including the current instrument and the - * shape of the amplitude envelope it produces. + * Note that this value does not necessarily reflect the instantaneous level + * of the sound produced by this voice; that level is the result of many + * contributing factors, including the current instrument and the shape of + * the amplitude envelope it produces. * * @see #active */ diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiFileReader.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiFileReader.java index ecb72b32dd2..bbdca9e97bb 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiFileReader.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/MidiFileReader.java @@ -26,13 +26,13 @@ package javax.sound.midi.spi; import java.io.File; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.net.URL; +import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MidiFileFormat; import javax.sound.midi.Sequence; -import javax.sound.midi.InvalidMidiDataException; /** * A {@code MidiFileReader} supplies MIDI file-reading services. Classes @@ -106,7 +106,7 @@ public abstract class MidiFileReader { * @param stream the input stream from which the {@code Sequence} should * be constructed * @return a {@code Sequence} object based on the MIDI file data contained - * in the input stream. + * in the input stream * @throws InvalidMidiDataException if the stream does not point to valid * MIDI file data recognized by the system * @throws IOException if an I/O exception occurs diff --git a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/SoundbankReader.java b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/SoundbankReader.java index c7e82d9960f..501c18b6ad5 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/SoundbankReader.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/midi/spi/SoundbankReader.java @@ -32,12 +32,12 @@ import java.net.URL; import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.Soundbank; +import javax.sound.midi.Synthesizer; /** * A {@code SoundbankReader} supplies soundbank file-reading services. Concrete * subclasses of {@code SoundbankReader} parse a given soundbank file, producing - * a {@link javax.sound.midi.Soundbank} object that can be loaded into a - * {@link javax.sound.midi.Synthesizer}. + * a {@link Soundbank} object that can be loaded into a {@link Synthesizer}. * * @since 1.3 * @author Kara Kytle @@ -47,7 +47,7 @@ public abstract class SoundbankReader { /** * Obtains a soundbank object from the URL provided. * - * @param url URL representing the soundbank. + * @param url URL representing the soundbank * @return soundbank object * @throws InvalidMidiDataException if the URL does not point to valid MIDI * soundbank data recognized by this soundbank reader diff --git a/jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioSystem.java b/jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioSystem.java index 459ef997855..db528aebb83 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioSystem.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/sampled/AudioSystem.java @@ -26,19 +26,19 @@ package javax.sound.sampled; import java.io.File; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.net.URL; - +import java.util.ArrayList; import java.util.HashSet; import java.util.List; +import java.util.Properties; import java.util.Set; import java.util.Vector; -import java.util.ArrayList; -import javax.sound.sampled.spi.AudioFileWriter; import javax.sound.sampled.spi.AudioFileReader; +import javax.sound.sampled.spi.AudioFileWriter; import javax.sound.sampled.spi.FormatConversionProvider; import javax.sound.sampled.spi.MixerProvider; @@ -60,14 +60,14 @@ import com.sun.media.sound.JDK13Services; *

    * Properties can be used to specify the default mixer for specific line types. * Both system properties and a properties file are considered. The - * {@code sound.properties} properties file is read from an - * implementation-specific location (typically it is the {@code lib} directory - * in the Java installation directory). If a property exists both as a system - * property and in the properties file, the system property takes precedence. - * If none is specified, a suitable default is chosen among the available - * devices. The syntax of the properties file is specified in - * {@link java.util.Properties#load(InputStream) Properties.load}. The following - * table lists the available property keys and which methods consider them: + * "sound.properties" properties file is read from an implementation-specific + * location (typically it is the {@code lib} directory in the Java installation + * directory). If a property exists both as a system property and in the + * properties file, the system property takes precedence. If none is specified, + * a suitable default is chosen among the available devices. The syntax of the + * properties file is specified in + * {@link Properties#load(InputStream) Properties.load}. The following table + * lists the available property keys and which methods consider them: * * * @@ -100,12 +100,11 @@ import com.sun.media.sound.JDK13Services; * * The property value consists of the provider class name and the mixer name, * separated by the hash mark ("#"). The provider class name is the - * fully-qualified name of a concrete - * {@link javax.sound.sampled.spi.MixerProvider mixer provider} class. The mixer - * name is matched against the {@code String} returned by the {@code getName} - * method of {@code Mixer.Info}. Either the class name, or the mixer name may be - * omitted. If only the class name is specified, the trailing hash mark is - * optional. + * fully-qualified name of a concrete {@link MixerProvider mixer provider} + * class. The mixer name is matched against the {@code String} returned by the + * {@code getName} method of {@code Mixer.Info}. Either the class name, or the + * mixer name may be omitted. If only the class name is specified, the trailing + * hash mark is optional. *

    * If the provider class is specified, and it can be successfully retrieved from * the installed providers, the list of {@code Mixer.Info} objects is retrieved @@ -1324,10 +1323,9 @@ public class AudioSystem { * Obtains the set of format converters (codecs, transcoders, etc.) that are * currently installed on the system. * - * @return an array of {@link javax.sound.sampled.spi.FormatConversionProvider - * FormatConversionProvider} objects representing the available - * format converters. If no format converters readers are available - * on the system, an array of length 0 is returned. + * @return an array of {@link FormatConversionProvider} objects representing + * the available format converters. If no format converters readers + * are available on the system, an array of length 0 is returned. */ @SuppressWarnings("unchecked") private static List getFormatConversionProviders() { @@ -1338,10 +1336,9 @@ public class AudioSystem { * Obtains the set of audio file readers that are currently installed on the * system. * - * @return a List of {@link javax.sound.sampled.spi.AudioFileReader - * AudioFileReader} objects representing the installed audio file - * readers. If no audio file readers are available on the system, an - * empty List is returned. + * @return a List of {@link AudioFileReader} objects representing the + * installed audio file readers. If no audio file readers are + * available on the system, an empty List is returned. */ @SuppressWarnings("unchecked") private static List getAudioFileReaders() { @@ -1352,10 +1349,9 @@ public class AudioSystem { * Obtains the set of audio file writers that are currently installed on the * system. * - * @return a List of {@link javax.sound.sampled.spi.AudioFileWriter - * AudioFileWriter} objects representing the available audio file - * writers. If no audio file writers are available on the system, an - * empty List is returned. + * @return a List of {@link AudioFileWriter} objects representing the + * available audio file writers. If no audio file writers are + * available on the system, an empty List is returned. */ @SuppressWarnings("unchecked") private static List getAudioFileWriters() { diff --git a/jdk/src/java.desktop/share/classes/javax/sound/sampled/DataLine.java b/jdk/src/java.desktop/share/classes/javax/sound/sampled/DataLine.java index 9a81a76c5b6..6246a40d64f 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/sampled/DataLine.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/sampled/DataLine.java @@ -355,11 +355,11 @@ public interface DataLine extends Line { * {@code true} for all formats returned by {@code getFormats()}. *

    * Some fields in the AudioFormat instances can be set to - * {@link javax.sound.sampled.AudioSystem#NOT_SPECIFIED NOT_SPECIFIED} - * if that field does not apply to the format, or if the format supports - * a wide range of values for that field. For example, a multi-channel - * device supporting up to 64 channels, could set the channel field in - * the {@code AudioFormat} instances returned by this method to + * {@link AudioSystem#NOT_SPECIFIED NOT_SPECIFIED} if that field does + * not apply to the format, or if the format supports a wide range of + * values for that field. For example, a multi-channel device supporting + * up to 64 channels, could set the channel field in the + * {@code AudioFormat} instances returned by this method to * {@code NOT_SPECIFIED}. * * @return a set of supported audio formats diff --git a/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileReader.java b/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileReader.java index daa75556785..818df436f49 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileReader.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileReader.java @@ -26,8 +26,8 @@ package javax.sound.sampled.spi; import java.io.File; -import java.io.InputStream; import java.io.IOException; +import java.io.InputStream; import java.net.URL; import javax.sound.sampled.AudioFileFormat; diff --git a/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileWriter.java b/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileWriter.java index a4cc31bdf18..0cb6dc6acae 100644 --- a/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileWriter.java +++ b/jdk/src/java.desktop/share/classes/javax/sound/sampled/spi/AudioFileWriter.java @@ -30,6 +30,7 @@ import java.io.IOException; import java.io.OutputStream; import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; import static javax.sound.sampled.AudioFileFormat.Type; @@ -110,8 +111,7 @@ public abstract class AudioFileWriter { * the length be written into the file header, and cannot be written from * start to finish unless the length is known in advance. An attempt to * write such a file type will fail with an IOException if the length in the - * audio file format is {@link javax.sound.sampled.AudioSystem#NOT_SPECIFIED - * AudioSystem.NOT_SPECIFIED}. + * audio file format is {@link AudioSystem#NOT_SPECIFIED}. * * @param stream the audio input stream containing audio data to be written * to the output stream diff --git a/jdk/src/java.desktop/share/classes/javax/swing/CellEditor.java b/jdk/src/java.desktop/share/classes/javax/swing/CellEditor.java index f1b625b7969..bf9a23d2f77 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/CellEditor.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/CellEditor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -47,7 +47,7 @@ import javax.swing.event.*; * new component implement the interface. Or the developer can * choose a wrapper based approach and provide a companion object which * implements the CellEditor interface (See - * JCellEditor for example). The wrapper approach + * DefaultCellEditor for example). The wrapper approach * is particularly useful if the user want to use a 3rd party ISV * editor with JTable, but the ISV didn't implement the * CellEditor interface. The user can simply create an object diff --git a/jdk/src/java.desktop/share/classes/javax/swing/ImageIcon.java b/jdk/src/java.desktop/share/classes/javax/swing/ImageIcon.java index 8f7812e5919..564e173c5c8 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/ImageIcon.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/ImageIcon.java @@ -490,12 +490,33 @@ public class ImageIcon implements Icon, Serializable, Accessible { private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { - s.defaultReadObject(); + ObjectInputStream.GetField f = s.readFields(); + + imageObserver = (ImageObserver) f.get("imageObserver", null); + description = (String) f.get("description", null); + width = f.get("width", -1); + height = f.get("height", -1); + accessibleContext = (AccessibleImageIcon) f.get("accessibleContext", null); int w = s.readInt(); int h = s.readInt(); int[] pixels = (int[])(s.readObject()); + if (pixels == null && (w != -1 || h != -1)) { + throw new IllegalStateException("Inconsistent width and height" + + " for null image [" + w + ", " + h + "]"); + } + + if (pixels != null && (w < 0 || h < 0)) { + throw new IllegalStateException("Inconsistent width and height" + + " for image [" + w + ", " + h + "]"); + } + + if (w != getIconWidth() || h != getIconHeight()) { + throw new IllegalStateException("Inconsistent width and height" + + " for image [" + w + ", " + h + "]"); + } + if (pixels != null) { Toolkit tk = Toolkit.getDefaultToolkit(); ColorModel cm = ColorModel.getRGBdefault(); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java index 765610ebbad..17cbf60100b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JComponent.java @@ -1888,7 +1888,7 @@ public abstract class JComponent extends Container implements Serializable, * description: The preferred vertical alignment of the component. */ public void setAlignmentY(float alignmentY) { - this.alignmentY = alignmentY > 1.0f ? 1.0f : alignmentY < 0.0f ? 0.0f : alignmentY; + this.alignmentY = validateAlignment(alignmentY); isAlignmentYSet = true; } @@ -1917,10 +1917,14 @@ public abstract class JComponent extends Container implements Serializable, * description: The preferred horizontal alignment of the component. */ public void setAlignmentX(float alignmentX) { - this.alignmentX = alignmentX > 1.0f ? 1.0f : alignmentX < 0.0f ? 0.0f : alignmentX; + this.alignmentX = validateAlignment(alignmentX); isAlignmentXSet = true; } + private float validateAlignment(float alignment) { + return alignment > 1.0f ? 1.0f : alignment < 0.0f ? 0.0f : alignment; + } + /** * Sets the input verifier for this component. * @@ -5514,7 +5518,24 @@ public abstract class JComponent extends Container implements Serializable, private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { - s.defaultReadObject(); + ObjectInputStream.GetField f = s.readFields(); + + isAlignmentXSet = f.get("isAlignmentXSet", false); + alignmentX = validateAlignment(f.get("alignmentX", 0f)); + isAlignmentYSet = f.get("isAlignmentYSet", false); + alignmentY = validateAlignment(f.get("alignmentY", 0f)); + listenerList = (EventListenerList) f.get("listenerList", null); + vetoableChangeSupport = (VetoableChangeSupport) f.get("vetoableChangeSupport", null); + autoscrolls = f.get("autoscrolls", false); + border = (Border) f.get("border", null); + flags = f.get("flags", 0); + inputVerifier = (InputVerifier) f.get("inputVerifier", null); + verifyInputWhenFocusTarget = f.get("verifyInputWhenFocusTarget", false); + popupMenu = (JPopupMenu) f.get("popupMenu", null); + focusInputMap = (InputMap) f.get("focusInputMap", null); + ancestorInputMap = (InputMap) f.get("ancestorInputMap", null); + windowInputMap = (ComponentInputMap) f.get("windowInputMap", null); + actionMap = (ActionMap) f.get("actionMap", null); /* If there's no ReadObjectCallback for this stream yet, that is, if * this is the first call to JComponent.readObject() for this diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java b/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java index bf690ddbb5b..1edf4943357 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JFileChooser.java @@ -50,6 +50,8 @@ import java.awt.Toolkit; import java.awt.event.*; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; +import java.io.InvalidObjectException; +import java.io.ObjectInputStream; import java.lang.ref.WeakReference; /** @@ -460,10 +462,14 @@ public class JFileChooser extends JComponent implements Accessible { * bound: false */ public void setDragEnabled(boolean b) { + checkDragEnabled(b); + dragEnabled = b; + } + + private static void checkDragEnabled(boolean b) { if (b && GraphicsEnvironment.isHeadless()) { throw new HeadlessException(); } - dragEnabled = b; } /** @@ -949,9 +955,7 @@ public class JFileChooser extends JComponent implements Accessible { if(this.dialogType == dialogType) { return; } - if(!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG || dialogType == CUSTOM_DIALOG)) { - throw new IllegalArgumentException("Incorrect Dialog Type: " + dialogType); - } + checkDialogType(dialogType); int oldValue = this.dialogType; this.dialogType = dialogType; if(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG) { @@ -960,6 +964,14 @@ public class JFileChooser extends JComponent implements Accessible { firePropertyChange(DIALOG_TYPE_CHANGED_PROPERTY, oldValue, dialogType); } + private static void checkDialogType(int dialogType) { + if (!(dialogType == OPEN_DIALOG || dialogType == SAVE_DIALOG + || dialogType == CUSTOM_DIALOG)) { + throw new IllegalArgumentException( + "Incorrect Dialog Type: " + dialogType); + } + } + /** * Sets the string that goes in the JFileChooser window's * title bar. @@ -1349,12 +1361,17 @@ public class JFileChooser extends JComponent implements Accessible { return; } - if ((mode == FILES_ONLY) || (mode == DIRECTORIES_ONLY) || (mode == FILES_AND_DIRECTORIES)) { + checkFileSelectionMode(mode); int oldValue = fileSelectionMode; fileSelectionMode = mode; firePropertyChange(FILE_SELECTION_MODE_CHANGED_PROPERTY, oldValue, fileSelectionMode); - } else { - throw new IllegalArgumentException("Incorrect Mode for file selection: " + mode); + } + + private static void checkFileSelectionMode(int mode) { + if ((mode != FILES_ONLY) && (mode != DIRECTORIES_ONLY) + && (mode != FILES_AND_DIRECTORIES)) { + throw new IllegalArgumentException( + "Incorrect Mode for file selection: " + mode); } } @@ -1901,7 +1918,43 @@ public class JFileChooser extends JComponent implements Accessible { */ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); + ObjectInputStream.GetField f = in.readFields(); + + dialogTitle = (String) f.get("dialogTitle", null); + approveButtonText = (String) f.get("approveButtonText", null); + approveButtonToolTipText = + (String) f.get("approveButtonToolTipText", null); + approveButtonMnemonic = f.get("approveButtonMnemonic", 0); + @SuppressWarnings("unchecked") + Vector newFilters = (Vector) f.get("filters", null); + if (newFilters == null) { + throw new InvalidObjectException("Null filters"); + } + filters = newFilters; + dialog = (JDialog) f.get("dialog", null); + int newDialogType = f.get("dialogType", OPEN_DIALOG); + checkDialogType(newDialogType); + dialogType = newDialogType; + returnValue = f.get("returnValue", 0); + accessory = (JComponent) f.get("accessory", null); + fileView = (FileView) f.get("fileView", null); + controlsShown = f.get("controlsShown", false); + useFileHiding = f.get("useFileHiding", false); + int newFileSelectionMode = f.get("fileSelectionMode", FILES_ONLY); + checkFileSelectionMode(newFileSelectionMode); + fileSelectionMode = newFileSelectionMode; + multiSelectionEnabled = f.get("multiSelectionEnabled", false); + useAcceptAllFileFilter = f.get("useAcceptAllFileFilter", false); + boolean newDragEnabled = f.get("dragEnabled", false); + checkDragEnabled(newDragEnabled); + dragEnabled = newDragEnabled; + fileFilter = (FileFilter) f.get("fileFilter", null); + fileSystemView = (FileSystemView) f.get("fileSystemView", null); + currentDirectory = (File) f.get("currentDirectory", null); + selectedFile = (File) f.get("selectedFile", null); + selectedFiles = (File[]) f.get("selectedFiles", null); + accessibleContext = (AccessibleContext) f.get("accessibleContext", null); + installShowFilesListener(); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JFrame.java b/jdk/src/java.desktop/share/classes/javax/swing/JFrame.java index cc3b0807f96..9de3edef45a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JFrame.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JFrame.java @@ -24,14 +24,22 @@ */ package javax.swing; -import java.awt.*; -import java.awt.event.*; -import java.beans.PropertyChangeListener; -import java.util.Locale; -import java.util.Vector; -import java.io.Serializable; +import java.awt.AWTEvent; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Container; +import java.awt.Frame; +import java.awt.Graphics; +import java.awt.GraphicsConfiguration; +import java.awt.HeadlessException; +import java.awt.Image; +import java.awt.LayoutManager; +import java.awt.event.WindowEvent; -import javax.accessibility.*; +import javax.accessibility.Accessible; +import javax.accessibility.AccessibleContext; +import javax.accessibility.AccessibleState; +import javax.accessibility.AccessibleStateSet; /** @@ -297,33 +305,28 @@ public class JFrame extends Frame implements WindowConstants, * @see #setDefaultCloseOperation * @see java.awt.Window#processWindowEvent */ - protected void processWindowEvent(WindowEvent e) { + protected void processWindowEvent(final WindowEvent e) { super.processWindowEvent(e); if (e.getID() == WindowEvent.WINDOW_CLOSING) { - switch(defaultCloseOperation) { - case HIDE_ON_CLOSE: - setVisible(false); - break; - case DISPOSE_ON_CLOSE: - dispose(); - break; - case DO_NOTHING_ON_CLOSE: - default: - break; - case EXIT_ON_CLOSE: - // This needs to match the checkExit call in - // setDefaultCloseOperation - System.exit(0); - break; + switch (defaultCloseOperation) { + case HIDE_ON_CLOSE: + setVisible(false); + break; + case DISPOSE_ON_CLOSE: + dispose(); + break; + case EXIT_ON_CLOSE: + // This needs to match the checkExit call in + // setDefaultCloseOperation + System.exit(0); + break; + case DO_NOTHING_ON_CLOSE: + default: } } } -// public void setMenuBar(MenuBar menu) { -// throw new IllegalComponentStateException("Please use setJMenuBar() with JFrame."); -// } - /** * Sets the operation that will happen by default when * the user initiates a "close" on this frame. diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JLayer.java b/jdk/src/java.desktop/share/classes/javax/swing/JLayer.java index 57bccae7ec6..8c58c916a4e 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JLayer.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JLayer.java @@ -158,8 +158,9 @@ public final class JLayer private LayerUI layerUI; private JPanel glassPane; private long eventMask; - private transient boolean isPainting; - private transient boolean isPaintingImmediately; + private transient boolean isPaintCalling; + private transient boolean isPaintImmediatelyCalling; + private transient boolean isImageUpdateCalling; private static final LayerEventController eventController = new LayerEventController(); @@ -405,30 +406,57 @@ public final class JLayer * @param h the height of the region to be painted */ public void paintImmediately(int x, int y, int w, int h) { - if (!isPaintingImmediately && getUI() != null) { - isPaintingImmediately = true; + if (!isPaintImmediatelyCalling && getUI() != null) { + isPaintImmediatelyCalling = true; try { getUI().paintImmediately(x, y, w, h, this); } finally { - isPaintingImmediately = false; + isPaintImmediatelyCalling = false; } } else { super.paintImmediately(x, y, w, h); } } + /** + * Delegates its functionality to the + * {@link javax.swing.plaf.LayerUI#imageUpdate(java.awt.Image, int, int, int, int, int, JLayer)} method, + * if the {@code LayerUI} is set. + * + * @param img the image being observed + * @param infoflags see {@code imageUpdate} for more information + * @param x the x coordinate + * @param y the y coordinate + * @param w the width + * @param h the height + * @return {@code false} if the infoflags indicate that the + * image is completely loaded; {@code true} otherwise. + */ + public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h) { + if (!isImageUpdateCalling && getUI() != null) { + isImageUpdateCalling = true; + try { + return getUI().imageUpdate(img, infoflags, x, y, w, h, this); + } finally { + isImageUpdateCalling = false; + } + } else { + return super.imageUpdate(img, infoflags, x, y, w, h); + } + } + /** * Delegates all painting to the {@link javax.swing.plaf.LayerUI} object. * * @param g the {@code Graphics} to render to */ public void paint(Graphics g) { - if (!isPainting) { - isPainting = true; + if (!isPaintCalling) { + isPaintCalling = true; try { super.paintComponent(g); } finally { - isPainting = false; + isPaintCalling = false; } } else { super.paint(g); @@ -646,15 +674,21 @@ public final class JLayer return 1; } + @SuppressWarnings("unchecked") private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { - s.defaultReadObject(); - if (layerUI != null) { - setUI(layerUI); - } + ObjectInputStream.GetField f = s.readFields(); + + view = (V) f.get("view", null); + glassPane = (JPanel) f.get("glassPane", null); + eventMask = f.get("eventMask", 0l); if (eventMask != 0) { eventController.updateAWTEventListener(0, eventMask); } + LayerUI newLayerUI = (LayerUI) f.get("layerUI", null); + if (newLayerUI != null) { + setUI(newLayerUI); + } } /** diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JOptionPane.java b/jdk/src/java.desktop/share/classes/javax/swing/JOptionPane.java index b3d52fc5274..413b3cfab73 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JOptionPane.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JOptionPane.java @@ -43,13 +43,10 @@ import java.awt.event.WindowEvent; import java.awt.event.ComponentAdapter; import java.awt.event.ComponentEvent; import java.io.IOException; +import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import java.lang.reflect.Method; -import java.lang.reflect.InvocationTargetException; -import java.security.AccessController; -import java.security.PrivilegedAction; import java.util.Vector; import javax.swing.plaf.OptionPaneUI; import javax.swing.event.InternalFrameEvent; @@ -2055,15 +2052,22 @@ public class JOptionPane extends JComponent implements Accessible * description: The option pane's message type. */ public void setMessageType(int newType) { + checkMessageType(newType); + int oldType = messageType; + messageType = newType; + firePropertyChange(MESSAGE_TYPE_PROPERTY, oldType, messageType); + } + + private static void checkMessageType(int newType){ if(newType != ERROR_MESSAGE && newType != INFORMATION_MESSAGE && newType != WARNING_MESSAGE && newType != QUESTION_MESSAGE && newType != PLAIN_MESSAGE) - throw new RuntimeException("JOptionPane: type must be one of JOptionPane.ERROR_MESSAGE, JOptionPane.INFORMATION_MESSAGE, JOptionPane.WARNING_MESSAGE, JOptionPane.QUESTION_MESSAGE or JOptionPane.PLAIN_MESSAGE"); - - int oldType = messageType; - - messageType = newType; - firePropertyChange(MESSAGE_TYPE_PROPERTY, oldType, messageType); + throw new RuntimeException("JOptionPane: type must be one of" + + " JOptionPane.ERROR_MESSAGE," + + " JOptionPane.INFORMATION_MESSAGE," + + " JOptionPane.WARNING_MESSAGE," + + " JOptionPane.QUESTION_MESSAGE" + + " or JOptionPane.PLAIN_MESSAGE"); } /** @@ -2097,16 +2101,23 @@ public class JOptionPane extends JComponent implements Accessible * description: The option pane's option type. */ public void setOptionType(int newType) { - if(newType != DEFAULT_OPTION && newType != YES_NO_OPTION && - newType != YES_NO_CANCEL_OPTION && newType != OK_CANCEL_OPTION) - throw new RuntimeException("JOptionPane: option type must be one of JOptionPane.DEFAULT_OPTION, JOptionPane.YES_NO_OPTION, JOptionPane.YES_NO_CANCEL_OPTION or JOptionPane.OK_CANCEL_OPTION"); - + checkOptionType(newType); int oldType = optionType; - optionType = newType; firePropertyChange(OPTION_TYPE_PROPERTY, oldType, optionType); } + private static void checkOptionType(int newType) { + if (newType != DEFAULT_OPTION && newType != YES_NO_OPTION + && newType != YES_NO_CANCEL_OPTION + && newType != OK_CANCEL_OPTION) { + throw new RuntimeException("JOptionPane: option type must be one of" + + " JOptionPane.DEFAULT_OPTION, JOptionPane.YES_NO_OPTION," + + " JOptionPane.YES_NO_CANCEL_OPTION" + + " or JOptionPane.OK_CANCEL_OPTION"); + } + } + /** * Returns the type of options that are displayed. * @@ -2385,7 +2396,15 @@ public class JOptionPane extends JComponent implements Accessible private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { - s.defaultReadObject(); + ObjectInputStream.GetField f = s.readFields(); + + int newMessageType = f.get("messageType", 0); + checkMessageType(newMessageType); + messageType = newMessageType; + int newOptionType = f.get("optionType", 0); + checkOptionType(newOptionType); + optionType = newOptionType; + wantsInput = f.get("wantsInput", false); Vector values = (Vector)s.readObject(); int indexCounter = 0; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JPopupMenu.java b/jdk/src/java.desktop/share/classes/javax/swing/JPopupMenu.java index ca00144b774..89311ba1228 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JPopupMenu.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JPopupMenu.java @@ -1345,7 +1345,20 @@ public class JPopupMenu extends JComponent implements Accessible,MenuElement { // implements javax.swing.MenuElement private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { - s.defaultReadObject(); + ObjectInputStream.GetField f = s.readFields(); + + int newDesiredLocationX = f.get("desiredLocationX", 0); + int newDesiredLocationY = f.get("desiredLocationY", 0); + Point p = adjustPopupLocationToFitScreen( + newDesiredLocationX, newDesiredLocationY); + desiredLocationX = p.x; + desiredLocationY = p.y; + + label = (String) f.get("label", null); + paintBorder = f.get("paintBorder", false); + margin = (Insets) f.get("margin", null); + lightWeightPopup = f.get("lightWeightPopup", false); + selectionModel = (SingleSelectionModel) f.get("selectionModel", null); Vector values = (Vector)s.readObject(); int indexCounter = 0; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JSlider.java b/jdk/src/java.desktop/share/classes/javax/swing/JSlider.java index 39e960f9a75..956c57a166c 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JSlider.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JSlider.java @@ -138,8 +138,11 @@ public class JSlider extends JComponent implements SwingConstants, Accessible { /** * {@code Dictionary} of what labels to draw at which values */ - private Dictionary labelTable; - + @SuppressWarnings("rawtypes") + private Dictionary labelTable; + // For better source compatibility, the labelTable field and + // associated getter and setter methods are being left as raw + // types. /** * The changeListener (no suffix) is the listener we add to the @@ -773,10 +776,10 @@ public class JSlider extends JComponent implements SwingConstants, Accessible { } // Check that there is a label with such image - Enumeration elements = labelTable.elements(); + Enumeration elements = labelTable.elements(); while (elements.hasMoreElements()) { - JComponent component = elements.nextElement(); + Component component = (Component) elements.nextElement(); if (component instanceof JLabel) { JLabel label = (JLabel) component; @@ -797,7 +800,8 @@ public class JSlider extends JComponent implements SwingConstants, Accessible { * @return the Dictionary containing labels and * where to draw them */ - public Dictionary getLabelTable() { + @SuppressWarnings("rawtypes") + public Dictionary getLabelTable() { /* if ( labelTable == null && getMajorTickSpacing() > 0 ) { setLabelTable( createStandardLabels( getMajorTickSpacing() ) ); @@ -830,8 +834,9 @@ public class JSlider extends JComponent implements SwingConstants, Accessible { * attribute: visualUpdate true * description: Specifies what labels will be drawn for any given value. */ - public void setLabelTable( Dictionary labels ) { - Dictionary oldTable = labelTable; + @SuppressWarnings("rawtypes") + public void setLabelTable( Dictionary labels ) { + Dictionary oldTable = labelTable; labelTable = labels; updateLabelUIs(); firePropertyChange("labelTable", oldTable, labelTable ); @@ -852,25 +857,27 @@ public class JSlider extends JComponent implements SwingConstants, Accessible { * @see JComponent#updateUI */ protected void updateLabelUIs() { - Dictionary labelTable = getLabelTable(); + @SuppressWarnings("rawtypes") + Dictionary labelTable = getLabelTable(); if (labelTable == null) { return; } - Enumeration labels = labelTable.keys(); + Enumeration labels = labelTable.keys(); while ( labels.hasMoreElements() ) { - JComponent component = labelTable.get(labels.nextElement()); + JComponent component = (JComponent) labelTable.get(labels.nextElement()); component.updateUI(); component.setSize(component.getPreferredSize()); } } private void updateLabelSizes() { - Dictionary labelTable = getLabelTable(); + @SuppressWarnings("rawtypes") + Dictionary labelTable = getLabelTable(); if (labelTable != null) { - Enumeration labels = labelTable.elements(); + Enumeration labels = labelTable.elements(); while (labels.hasMoreElements()) { - JComponent component = labels.nextElement(); + JComponent component = (JComponent) labels.nextElement(); component.setSize(component.getPreferredSize()); } } @@ -982,13 +989,13 @@ public class JSlider extends JComponent implements SwingConstants, Accessible { if ( e.getPropertyName().equals( "minimum" ) || e.getPropertyName().equals( "maximum" ) ) { - Enumeration keys = getLabelTable().keys(); + Enumeration keys = getLabelTable().keys(); Hashtable hashtable = new Hashtable<>(); // Save the labels that were added by the developer while ( keys.hasMoreElements() ) { - Integer key = keys.nextElement(); - JComponent value = labelTable.get(key); + Integer key = (Integer) keys.nextElement(); + JComponent value = (JComponent) labelTable.get(key); if ( !(value instanceof LabelUIResource) ) { hashtable.put( key, value ); } @@ -1000,7 +1007,7 @@ public class JSlider extends JComponent implements SwingConstants, Accessible { // Add the saved labels keys = hashtable.keys(); while ( keys.hasMoreElements() ) { - Integer key = keys.nextElement(); + Integer key = (Integer) keys.nextElement(); put( key, hashtable.get( key ) ); } @@ -1017,7 +1024,8 @@ public class JSlider extends JComponent implements SwingConstants, Accessible { SmartHashtable table = new SmartHashtable( increment, start ); - Dictionary labelTable = getLabelTable(); + @SuppressWarnings("rawtypes") + Dictionary labelTable = getLabelTable(); if (labelTable != null && (labelTable instanceof PropertyChangeListener)) { removePropertyChangeListener((PropertyChangeListener) labelTable); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java b/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java index 96c050529fe..ffde325f8d8 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTabbedPane.java @@ -495,10 +495,7 @@ public class JTabbedPane extends JComponent * */ public void setTabPlacement(int tabPlacement) { - if (tabPlacement != TOP && tabPlacement != LEFT && - tabPlacement != BOTTOM && tabPlacement != RIGHT) { - throw new IllegalArgumentException("illegal tab placement: must be TOP, BOTTOM, LEFT, or RIGHT"); - } + checkTabPlacement(tabPlacement); if (this.tabPlacement != tabPlacement) { int oldValue = this.tabPlacement; this.tabPlacement = tabPlacement; @@ -508,6 +505,14 @@ public class JTabbedPane extends JComponent } } + private static void checkTabPlacement(int tabPlacement) { + if (tabPlacement != TOP && tabPlacement != LEFT && + tabPlacement != BOTTOM && tabPlacement != RIGHT) { + throw new IllegalArgumentException("illegal tab placement:" + + " must be TOP, BOTTOM, LEFT, or RIGHT"); + } + } + /** * Returns the policy used by the tabbedpane to layout the tabs when all the * tabs will not fit within a single run. @@ -551,9 +556,7 @@ public class JTabbedPane extends JComponent * */ public void setTabLayoutPolicy(int tabLayoutPolicy) { - if (tabLayoutPolicy != WRAP_TAB_LAYOUT && tabLayoutPolicy != SCROLL_TAB_LAYOUT) { - throw new IllegalArgumentException("illegal tab layout policy: must be WRAP_TAB_LAYOUT or SCROLL_TAB_LAYOUT"); - } + checkTabLayoutPolicy(tabLayoutPolicy); if (this.tabLayoutPolicy != tabLayoutPolicy) { int oldValue = this.tabLayoutPolicy; this.tabLayoutPolicy = tabLayoutPolicy; @@ -563,6 +566,14 @@ public class JTabbedPane extends JComponent } } + private static void checkTabLayoutPolicy(int tabLayoutPolicy) { + if (tabLayoutPolicy != WRAP_TAB_LAYOUT + && tabLayoutPolicy != SCROLL_TAB_LAYOUT) { + throw new IllegalArgumentException("illegal tab layout policy:" + + " must be WRAP_TAB_LAYOUT or SCROLL_TAB_LAYOUT"); + } + } + /** * Returns the currently selected index for this tabbedpane. * Returns -1 if there is no currently selected tab. @@ -1816,7 +1827,19 @@ public class JTabbedPane extends JComponent private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { - s.defaultReadObject(); + ObjectInputStream.GetField f = s.readFields(); + + int newTabPlacement = f.get("tabPlacement", TOP); + checkTabPlacement(newTabPlacement); + tabPlacement = newTabPlacement; + int newTabLayoutPolicy = f.get("tabLayoutPolicy", 0); + checkTabLayoutPolicy(newTabLayoutPolicy); + tabLayoutPolicy = newTabLayoutPolicy; + model = (SingleSelectionModel) f.get("model", null); + haveRegistered = f.get("haveRegistered", false); + changeListener = (ChangeListener) f.get("changeListener", null); + visComp = (Component) f.get("visComp", null); + if ((ui != null) && (getUIClassID().equals(uiClassID))) { ui.installUI(this); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java index a4f30ac33a5..5e2d595403e 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTable.java @@ -37,6 +37,7 @@ import java.beans.*; import java.io.ObjectOutputStream; import java.io.ObjectInputStream; import java.io.IOException; +import java.io.InvalidObjectException; import javax.accessibility.*; @@ -669,7 +670,8 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * @param rowData the data for the new table * @param columnNames names of each column */ - public JTable(Vector> rowData, Vector columnNames) { + @SuppressWarnings("rawtypes") + public JTable(Vector rowData, Vector columnNames) { this(new DefaultTableModel(rowData, columnNames)); } @@ -1203,11 +1205,7 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * AUTO_RESIZE_ALL_COLUMNS JTable.AUTO_RESIZE_ALL_COLUMNS */ public void setAutoResizeMode(int mode) { - if ((mode == AUTO_RESIZE_OFF) || - (mode == AUTO_RESIZE_NEXT_COLUMN) || - (mode == AUTO_RESIZE_SUBSEQUENT_COLUMNS) || - (mode == AUTO_RESIZE_LAST_COLUMN) || - (mode == AUTO_RESIZE_ALL_COLUMNS)) { + if (isValidAutoResizeMode(mode)) { int old = autoResizeMode; autoResizeMode = mode; resizeAndRepaint(); @@ -1218,6 +1216,14 @@ public class JTable extends JComponent implements TableModelListener, Scrollable } } + private static boolean isValidAutoResizeMode(int mode) { + return (mode == AUTO_RESIZE_OFF) + || (mode == AUTO_RESIZE_NEXT_COLUMN) + || (mode == AUTO_RESIZE_SUBSEQUENT_COLUMNS) + || (mode == AUTO_RESIZE_LAST_COLUMN) + || (mode == AUTO_RESIZE_ALL_COLUMNS); + } + /** * Returns the auto resize mode of the table. The default mode * is AUTO_RESIZE_SUBSEQUENT_COLUMNS. @@ -1439,10 +1445,14 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * bound: false */ public void setDragEnabled(boolean b) { + checkDragEnabled(b); + dragEnabled = b; + } + + private void checkDragEnabled(boolean b) { if (b && GraphicsEnvironment.isHeadless()) { throw new HeadlessException(); } - dragEnabled = b; } /** @@ -1489,6 +1499,11 @@ public class JTable extends JComponent implements TableModelListener, Scrollable * @since 1.6 */ public final void setDropMode(DropMode dropMode) { + checkDropMode(dropMode); + this.dropMode = dropMode; + } + + private static void checkDropMode(DropMode dropMode) { if (dropMode != null) { switch (dropMode) { case USE_SELECTION: @@ -1499,14 +1514,12 @@ public class JTable extends JComponent implements TableModelListener, Scrollable case ON_OR_INSERT: case ON_OR_INSERT_ROWS: case ON_OR_INSERT_COLS: - this.dropMode = dropMode; return; } } - - throw new IllegalArgumentException(dropMode + ": Unsupported drop mode for table"); + throw new IllegalArgumentException(dropMode + + ": Unsupported drop mode for table"); } - /** * Returns the drop mode for this component. * @@ -5865,7 +5878,75 @@ public class JTable extends JComponent implements TableModelListener, Scrollable private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { - s.defaultReadObject(); + ObjectInputStream.GetField f = s.readFields(); + + TableModel newDataModel = (TableModel) f.get("dataModel", null); + if (newDataModel == null) { + throw new InvalidObjectException("Null dataModel"); + } + dataModel = newDataModel; + + TableColumnModel newColumnModel = (TableColumnModel) f.get("columnModel", null); + if (newColumnModel == null) { + throw new InvalidObjectException("Null columnModel"); + } + columnModel = newColumnModel; + + ListSelectionModel newSelectionModel = (ListSelectionModel) f.get("selectionModel", null); + if (newSelectionModel == null) { + throw new InvalidObjectException("Null selectionModel"); + } + selectionModel = newSelectionModel; + + tableHeader = (JTableHeader) f.get("tableHeader", null); + int newRowHeight = f.get("rowHeight", 0); + if (newRowHeight <= 0) { + throw new InvalidObjectException("Row height less than 1"); + } + rowHeight = newRowHeight; + + rowMargin = f.get("rowMargin", 0); + Color newGridColor = (Color) f.get("gridColor", null); + if (newGridColor == null) { + throw new InvalidObjectException("Null gridColor"); + } + gridColor = newGridColor; + + showHorizontalLines = f.get("showHorizontalLines", false); + showVerticalLines = f.get("showVerticalLines", false); + int newAutoResizeMode = f.get("autoResizeMode", 0); + if (!isValidAutoResizeMode(newAutoResizeMode)) { + throw new InvalidObjectException("autoResizeMode is not valid"); + } + autoResizeMode = newAutoResizeMode; + autoCreateColumnsFromModel = f.get("autoCreateColumnsFromModel", false); + preferredViewportSize = (Dimension) f.get("preferredViewportSize", null); + rowSelectionAllowed = f.get("rowSelectionAllowed", false); + cellSelectionEnabled = f.get("cellSelectionEnabled", false); + selectionForeground = (Color) f.get("selectionForeground", null); + selectionBackground = (Color) f.get("selectionBackground", null); + rowModel = (SizeSequence) f.get("rowModel", null); + + boolean newDragEnabled = f.get("dragEnabled", false); + checkDragEnabled(newDragEnabled); + dragEnabled = newDragEnabled; + + surrendersFocusOnKeystroke = f.get("surrendersFocusOnKeystroke", false); + editorRemover = (PropertyChangeListener) f.get("editorRemover", null); + columnSelectionAdjusting = f.get("columnSelectionAdjusting", false); + rowSelectionAdjusting = f.get("rowSelectionAdjusting", false); + printError = (Throwable) f.get("printError", null); + isRowHeightSet = f.get("isRowHeightSet", false); + updateSelectionOnSort = f.get("updateSelectionOnSort", false); + ignoreSortChange = f.get("ignoreSortChange", false); + sorterChanged = f.get("sorterChanged", false); + autoCreateRowSorter = f.get("autoCreateRowSorter", false); + fillsViewportHeight = f.get("fillsViewportHeight", false); + DropMode newDropMode = (DropMode) f.get("dropMode", + DropMode.USE_SELECTION); + checkDropMode(newDropMode); + dropMode = newDropMode; + if ((ui != null) && (getUIClassID().equals(uiClassID))) { ui.installUI(this); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/JTree.java b/jdk/src/java.desktop/share/classes/javax/swing/JTree.java index 3188156e347..6d50f6f653a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/JTree.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/JTree.java @@ -1216,10 +1216,14 @@ public class JTree extends JComponent implements Scrollable, Accessible * bound: false */ public void setDragEnabled(boolean b) { + checkDragEnabled(b); + dragEnabled = b; + } + + private static void checkDragEnabled(boolean b) { if (b && GraphicsEnvironment.isHeadless()) { throw new HeadlessException(); } - dragEnabled = b; } /** @@ -1262,18 +1266,23 @@ public class JTree extends JComponent implements Scrollable, Accessible * @since 1.6 */ public final void setDropMode(DropMode dropMode) { + checkDropMode(dropMode); + this.dropMode = dropMode; + } + + private static void checkDropMode(DropMode dropMode) { if (dropMode != null) { switch (dropMode) { case USE_SELECTION: case ON: case INSERT: case ON_OR_INSERT: - this.dropMode = dropMode; return; } } - throw new IllegalArgumentException(dropMode + ": Unsupported drop mode for tree"); + throw new IllegalArgumentException(dropMode + + ": Unsupported drop mode for tree"); } /** @@ -3089,7 +3098,34 @@ public class JTree extends JComponent implements Scrollable, Accessible private void readObject(ObjectInputStream s) throws IOException, ClassNotFoundException { - s.defaultReadObject(); + ObjectInputStream.GetField f = s.readFields(); + + rootVisible = f.get("rootVisible", false); + rowHeight = f.get("rowHeight", 0); + rowHeightSet = f.get("rowHeightSet", false); + showsRootHandles = f.get("showsRootHandles", false); + showsRootHandlesSet = f.get("showsRootHandlesSet", false); + editable = f.get("editable", false); + largeModel = f.get("largeModel", false); + visibleRowCount = f.get("visibleRowCount", 0); + invokesStopCellEditing = f.get("invokesStopCellEditing", false); + scrollsOnExpand = f.get("scrollsOnExpand", false); + scrollsOnExpandSet = f.get("scrollsOnExpandSet", false); + toggleClickCount = f.get("toggleClickCount", 0); + leadPath = (TreePath) f.get("leadPath", null); + anchorPath = (TreePath) f.get("anchorPath", null); + expandsSelectedPaths = f.get("expandsSelectedPaths", false); + settingUI = f.get("settingUI", false); + boolean newDragEnabled = f.get("dragEnabled", false); + checkDragEnabled(newDragEnabled); + dragEnabled = newDragEnabled; + DropMode newDropMode = (DropMode) f.get("dropMode", + DropMode.USE_SELECTION); + checkDropMode(newDropMode); + dropMode = newDropMode; + + expandRow = f.get("expandRow", -1); + dropTimer = (TreeTimer) f.get("dropTimer", null); // Create an instance of expanded state. diff --git a/jdk/src/java.desktop/share/classes/javax/swing/LegacyGlueFocusTraversalPolicy.java b/jdk/src/java.desktop/share/classes/javax/swing/LegacyGlueFocusTraversalPolicy.java index de33d4c4dae..ac366ca8df6 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/LegacyGlueFocusTraversalPolicy.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/LegacyGlueFocusTraversalPolicy.java @@ -194,7 +194,23 @@ final class LegacyGlueFocusTraversalPolicy extends FocusTraversalPolicy private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); + ObjectInputStream.GetField f = in.readFields(); + + @SuppressWarnings("unchecked") + HashMap newForwardMap = + (HashMap ) f.get("forwardMap", null); + if (newForwardMap == null) { + throw new InvalidObjectException("Null forwardMap"); + } + forwardMap = newForwardMap; + @SuppressWarnings("unchecked") + HashMap newBackwardMap = + (HashMap) f.get("backwardMap", null); + if (newBackwardMap == null) { + throw new InvalidObjectException("Null backwardMap"); + } + backwardMap = newBackwardMap; + delegatePolicy = (FocusTraversalPolicy)in.readObject(); delegateManager = (DefaultFocusManager)in.readObject(); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java b/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java index fb7b2820fd2..07705f4a812 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/SwingUtilities.java @@ -374,7 +374,8 @@ public class SwingUtilities implements SwingConstants sourceWheelEvent.isPopupTrigger(), sourceWheelEvent.getScrollType(), sourceWheelEvent.getScrollAmount(), - sourceWheelEvent.getWheelRotation()); + sourceWheelEvent.getWheelRotation(), + sourceWheelEvent.getPreciseWheelRotation()); } else if (sourceEvent instanceof MenuDragMouseEvent) { MenuDragMouseEvent sourceMenuDragEvent = (MenuDragMouseEvent)sourceEvent; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/Timer.java b/jdk/src/java.desktop/share/classes/javax/swing/Timer.java index 6caced7dd8d..ffaa9d53b3c 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/Timer.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/Timer.java @@ -401,14 +401,15 @@ public class Timer implements Serializable * @see #setInitialDelay */ public void setDelay(int delay) { - if (delay < 0) { - throw new IllegalArgumentException("Invalid delay: " + delay); - } - else { + checkDelay(delay, "Invalid delay: "); this.delay = delay; } - } + private static void checkDelay(int delay, String message) { + if (delay < 0) { + throw new IllegalArgumentException(message + delay); + } + } /** * Returns the delay, in milliseconds, @@ -435,14 +436,9 @@ public class Timer implements Serializable * @see #setDelay */ public void setInitialDelay(int initialDelay) { - if (initialDelay < 0) { - throw new IllegalArgumentException("Invalid initial delay: " + - initialDelay); - } - else { + checkDelay(initialDelay, "Invalid initial delay: "); this.initialDelay = initialDelay; } - } /** @@ -638,7 +634,26 @@ public class Timer implements Serializable throws ClassNotFoundException, IOException { this.acc = AccessController.getContext(); - in.defaultReadObject(); + ObjectInputStream.GetField f = in.readFields(); + + EventListenerList newListenerList = (EventListenerList) + f.get("listenerList", null); + if (newListenerList == null) { + throw new InvalidObjectException("Null listenerList"); + } + listenerList = newListenerList; + + int newInitialDelay = f.get("initialDelay", 0); + checkDelay(newInitialDelay, "Invalid initial delay: "); + initialDelay = newInitialDelay; + + int newDelay = f.get("delay", 0); + checkDelay(newDelay, "Invalid delay: "); + delay = newDelay; + + repeats = f.get("repeats", false); + coalesce = f.get("coalesce", false); + actionCommand = (String) f.get("actionCommand", null); } /* diff --git a/jdk/src/java.desktop/share/classes/javax/swing/event/SwingPropertyChangeSupport.java b/jdk/src/java.desktop/share/classes/javax/swing/event/SwingPropertyChangeSupport.java index 817a2f79bb8..3543e1c3720 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/event/SwingPropertyChangeSupport.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/event/SwingPropertyChangeSupport.java @@ -107,7 +107,7 @@ public final class SwingPropertyChangeSupport extends PropertyChangeSupport { * @see #SwingPropertyChangeSupport(Object sourceBean, boolean notifyOnEDT) * @since 1.6 */ - public final boolean isNotifyOnEDT() { + public boolean isNotifyOnEDT() { return notifyOnEDT; } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/ComboBoxUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/ComboBoxUI.java index e0d9f1fb7f9..2ba9741c770 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/ComboBoxUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/ComboBoxUI.java @@ -37,16 +37,25 @@ public abstract class ComboBoxUI extends ComponentUI { /** * Set the visibility of the popup + * + * @param c a {@code JComboBox} + * @param v a {@code boolean} determining the visibilty of the popup */ public abstract void setPopupVisible( JComboBox c, boolean v ); /** * Determine the visibility of the popup + * + * @param c a {@code JComboBox} + * @return true if popup of the {@code JComboBox} is visible */ public abstract boolean isPopupVisible( JComboBox c ); /** * Determine whether or not the combo box itself is traversable + * + * @param c a {@code JComboBox} + * @return true if the given {@code JComboBox} is traversable */ public abstract boolean isFocusTraversable( JComboBox c ); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/ComponentUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/ComponentUI.java index 190d450e09a..15a05cdd6b0 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/ComponentUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/ComponentUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -173,7 +173,8 @@ public abstract class ComponentUI { * this argument is often ignored, * but might be used if the UI object is stateless * and shared by multiple components - * + * @return a {@code Dimension} object containing given component's preferred + * size appropriate for the look and feel * @see javax.swing.JComponent#getPreferredSize * @see java.awt.LayoutManager#preferredLayoutSize */ @@ -240,7 +241,8 @@ public abstract class ComponentUI { * and shared by multiple components * @param x the x coordinate of the point * @param y the y coordinate of the point - * + * @return {@code true} if the specified {@code x,y} location is contained + * within the look and feel's defined shape for the given component * @see javax.swing.JComponent#contains * @see java.awt.Component#contains */ @@ -258,6 +260,9 @@ public abstract class ComponentUI { * stateful, then it should return a new instance per component. * The default implementation of this method throws an error, as it * should never be invoked. + * + * @param c a {@code JComponent} for which to create a UI delegate + * @return a {@code ComponentUI} object for {@code c} */ public static ComponentUI createUI(JComponent c) { throw new Error("ComponentUI.createUI not implemented."); @@ -332,8 +337,9 @@ public abstract class ComponentUI { * Component.AccessibleAWTComponent.getAccessibleChildrenCount() instead * of this method. * - * @see #getAccessibleChild + * @param c {@code JComponent} for which to get count of accessible children * @return the number of accessible children in the object + * @see #getAccessibleChild */ public int getAccessibleChildrenCount(JComponent c) { return SwingUtilities.getAccessibleChildrenCount(c); @@ -351,9 +357,10 @@ public abstract class ComponentUI { * Component.AccessibleAWTComponent.getAccessibleChild() instead of * this method. * - * @see #getAccessibleChildrenCount + * @param c a {@code JComponent} for which to get a child object * @param i zero-based index of child * @return the ith Accessible child of the object + * @see #getAccessibleChildrenCount */ public Accessible getAccessibleChild(JComponent c, int i) { return SwingUtilities.getAccessibleChild(c, i); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/FileChooserUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/FileChooserUI.java index d9b4361ae47..e3f2373b4cd 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/FileChooserUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/FileChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -52,6 +52,8 @@ public abstract class FileChooserUI extends ComponentUI * JFileChooser will use this button as default button * for dialog windows. * + * @param fc the {@code JFileChooser} whose default button is requested + * @return the default JButton for current look and feel * @since 1.7 */ public JButton getDefaultButton(JFileChooser fc) { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/LayerUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/LayerUI.java index a8584fd0fdc..a60da23517a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/LayerUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/LayerUI.java @@ -716,10 +716,22 @@ public class LayerUI * @param y the y value of the region to be painted * @param width the width of the region to be painted * @param height the height of the region to be painted - * + * @param l a {@code JLayer} component * @see JComponent#paintImmediately(int, int, int, int) */ public void paintImmediately(int x, int y, int width, int height, JLayer l) { l.paintImmediately(x, y, width, height); } + + /** + * Delegates its functionality to the default implementation of the {@code JLayer.imageUpdate} method + * which is inherited from {@code JLayer}'s base classes. + *

    + * This method is to be overridden instead of {@code JLayer.imageUpdate}. + *

    + * Note: This method is usually called not on the Event Dispatching Thread. + */ + public boolean imageUpdate(Image img, int infoflags, int x, int y, int w, int h, JLayer l) { + return l.imageUpdate(img, infoflags, x, y, w, h); + } } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/OptionPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/OptionPaneUI.java index 49137e7a0db..fc967b84315 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/OptionPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/OptionPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -38,12 +38,18 @@ public abstract class OptionPaneUI extends ComponentUI /** * Requests the component representing the default value to have * focus. + * + * @param op a {@code JOptionPane} */ public abstract void selectInitialValue(JOptionPane op); /** * Returns true if the user has supplied instances of Component for * either the options or message. + * + * @param op a {@code JOptionPane} + * @return {@code true} if the given {@code JOptionPane} contains user + * created {@code Component}s */ public abstract boolean containsCustomComponents(JOptionPane op); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/PopupMenuUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/PopupMenuUI.java index 5f57c659258..ab485a2c4ad 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/PopupMenuUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/PopupMenuUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2000, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -39,6 +39,11 @@ import javax.swing.JPopupMenu; public abstract class PopupMenuUI extends ComponentUI { /** + * Returns whether or not the given {@code MouseEvent} is the popup menu + * trigger event for the platform + * + * @param e a {@code MouseEvent} + * @return true if the {@code MouseEvent e} is the popup menu trigger * @since 1.3 */ public boolean isPopupTrigger(MouseEvent e) { diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/SplitPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/SplitPaneUI.java index ed62e39a4d7..15afcee9a0d 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/SplitPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/SplitPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -38,32 +38,49 @@ public abstract class SplitPaneUI extends ComponentUI /** * Messaged to relayout the JSplitPane based on the preferred size * of the children components. + * + * @param jc a {@code JSplitPane} */ public abstract void resetToPreferredSizes(JSplitPane jc); /** * Sets the location of the divider to location. + * + * @param jc a {@code JSplitPane} + * @param location an integer specifying the location of the divider */ public abstract void setDividerLocation(JSplitPane jc, int location); /** * Returns the location of the divider. + * + * @param jc a {@code JSplitPane} + * @return an integer specifying the location of the divider */ public abstract int getDividerLocation(JSplitPane jc); /** * Returns the minimum possible location of the divider. + * + * @param jc a {@code JSplitPane} + * @return and integer specifying the minimum location of the divider */ public abstract int getMinimumDividerLocation(JSplitPane jc); /** * Returns the maximum possible location of the divider. + * + * @param jc a {@code JSplitPane} + * @return an integer specifying the maximum location of the divider */ public abstract int getMaximumDividerLocation(JSplitPane jc); /** * Messaged after the JSplitPane the receiver is providing the look * and feel for paints its children. + * + * @param jc a {@code JSplitPane} + * @param g the {@code Graphics} context */ public abstract void finishedPaintingChildren(JSplitPane jc, Graphics g); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java index 0ce25c19071..6332d1ddc23 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/TextUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -42,8 +42,9 @@ public abstract class TextUI extends ComponentUI * Converts the given location in the model to a place in * the view coordinate system. * + * @param t the text component for which this UI is installed * @param pos the local location in the model to translate >= 0 - * @return the coordinates as a rectangle + * @return the coordinates as a {@code Rectangle} * @exception BadLocationException if the given position does not * represent a valid location in the associated document */ @@ -53,8 +54,10 @@ public abstract class TextUI extends ComponentUI * Converts the given location in the model to a place in * the view coordinate system. * + * @param t the text component for which this UI is installed * @param pos the local location in the model to translate >= 0 - * @return the coordinates as a rectangle + * @param bias the bias for the position + * @return the coordinates as a {@code Rectangle} * @exception BadLocationException if the given position does not * represent a valid location in the associated document */ @@ -64,6 +67,7 @@ public abstract class TextUI extends ComponentUI * Converts the given place in the view coordinate system * to the nearest representative location in the model. * + * @param t the text component for which this UI is installed * @param pt the location in the view to translate. This * should be in the same coordinate system as the mouse * events. @@ -75,6 +79,7 @@ public abstract class TextUI extends ComponentUI * Provides a mapping from the view coordinate space to the logical * coordinate space of the model. * + * @param t the text component for which this UI is installed * @param pt the location in the view to translate. * This should be in the same coordinate system * as the mouse events. @@ -117,6 +122,7 @@ public abstract class TextUI extends ComponentUI * Causes the portion of the view responsible for the * given part of the model to be repainted. * + * @param t the text component for which this UI is installed * @param p0 the beginning of the range >= 0 * @param p1 the end of the range >= p0 */ @@ -126,8 +132,13 @@ public abstract class TextUI extends ComponentUI * Causes the portion of the view responsible for the * given part of the model to be repainted. * + * @param t the text component for which this UI is installed * @param p0 the beginning of the range >= 0 * @param p1 the end of the range >= p0 + * @param firstBias the bias of the first character position, toward the + * previous character or the next character + * @param secondBias the bias of the second character position, toward the + * previous character or the next character */ public abstract void damageRange(JTextComponent t, int p0, int p1, Position.Bias firstBias, @@ -139,6 +150,7 @@ public abstract class TextUI extends ComponentUI * things like the commands available, stream readers and * writers, etc. * + * @param t the text component for which this UI is installed * @return the editor kit binding */ public abstract EditorKit getEditorKit(JTextComponent t); @@ -149,13 +161,18 @@ public abstract class TextUI extends ComponentUI * can be traversed to determine how the model is being * represented spatially. * - * @return the view + * @param t the text component for which this UI is installed + * @return a {@code View} with the allocation of the associated + * text component */ public abstract View getRootView(JTextComponent t); /** * Returns the string to be used as the tooltip at the passed in location. * + * @param t the text component for which this UI is installed + * @param pt a {@code Point} specifying location for which to get a tooltip + * @return a {@code String} containing the tooltip * @see javax.swing.text.JTextComponent#getToolTipText * @since 1.4 */ diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/TreeUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/TreeUI.java index d1ded67b15b..5968b335402 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/TreeUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/TreeUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 1998, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -38,68 +38,109 @@ import javax.swing.tree.TreePath; public abstract class TreeUI extends ComponentUI { /** - * Returns the Rectangle enclosing the label portion that the - * last item in path will be drawn into. Will return null if - * any component in path is currently valid. - */ + * Returns the Rectangle enclosing the label portion that the + * last item in path will be drawn into. Will return null if + * any component in path is currently valid. + * + * @param tree the {@code JTree} for {@code path} + * @param path the {@code TreePath} identifying the node + * @return the {@code Rectangle} enclosing the label portion that the + * last item in path will be drawn into, {@code null} if any + * component in path is currently valid. + */ public abstract Rectangle getPathBounds(JTree tree, TreePath path); /** - * Returns the path for passed in row. If row is not visible - * null is returned. - */ + * Returns the path for passed in row. If row is not visible + * null is returned. + * + * @param tree a {@code JTree} object + * @param row an integer specifying a row + * @return the {@code path} for {@code row} or {@code null} if {@code row} + * is not visible + */ public abstract TreePath getPathForRow(JTree tree, int row); /** - * Returns the row that the last item identified in path is visible - * at. Will return -1 if any of the elements in path are not - * currently visible. - */ + * Returns the row that the last item identified in path is visible + * at. Will return -1 if any of the elements in path are not + * currently visible. + * + * @param tree the {@code JTree} for {@code path} + * @param path the {@code TreePath} object to look in + * @return an integer specifying the row at which the last item + * identified is visible, -1 if any of the elements in + * {@code path} are not currently visible + */ public abstract int getRowForPath(JTree tree, TreePath path); /** - * Returns the number of rows that are being displayed. - */ + * Returns the number of rows that are being displayed. + * + * @param tree the {@code JTree} for which to count rows + * @return an integer specifying the number of row being displayed + */ public abstract int getRowCount(JTree tree); /** - * Returns the path to the node that is closest to x,y. If - * there is nothing currently visible this will return null, otherwise - * it'll always return a valid path. If you need to test if the - * returned object is exactly at x, y you should get the bounds for - * the returned path and test x, y against that. - */ + * Returns the path to the node that is closest to x,y. If + * there is nothing currently visible this will return null, otherwise + * it'll always return a valid path. If you need to test if the + * returned object is exactly at x, y you should get the bounds for + * the returned path and test x, y against that. + * + * @param tree a {@code JTree} object + * @param x an integer giving the number of pixels horizontally from the + * left edge of the display area + * @param y an integer giving the number of pixels vertically from the top + * of the display area, minus any top margin + * @return the {@code TreePath} node closest to {@code x,y} or {@code null} + * if there is nothing currently visible + */ public abstract TreePath getClosestPathForLocation(JTree tree, int x, int y); /** - * Returns true if the tree is being edited. The item that is being - * edited can be returned by getEditingPath(). - */ + * Returns true if the tree is being edited. The item that is being + * edited can be returned by getEditingPath(). + * + * @param tree a {@code JTree} object + * @return true if {@code tree} is being edited + */ public abstract boolean isEditing(JTree tree); /** - * Stops the current editing session. This has no effect if the - * tree isn't being edited. Returns true if the editor allows the - * editing session to stop. - */ + * Stops the current editing session. This has no effect if the + * tree isn't being edited. Returns true if the editor allows the + * editing session to stop. + * + * @param tree a {@code JTree} object + * @return true if the editor allows the editing session to stop + */ public abstract boolean stopEditing(JTree tree); /** - * Cancels the current editing session. This has no effect if the - * tree isn't being edited. Returns true if the editor allows the - * editing session to stop. - */ + * Cancels the current editing session. This has no effect if the + * tree isn't being edited. + * + * @param tree a {@code JTree} object + */ public abstract void cancelEditing(JTree tree); /** - * Selects the last item in path and tries to edit it. Editing will - * fail if the CellEditor won't allow it for the selected item. - */ + * Selects the last item in path and tries to edit it. Editing will + * fail if the CellEditor won't allow it for the selected item. + * + * @param tree the {@code JTree} being edited + * @param path the {@code TreePath} to be edited + */ public abstract void startEditingAtPath(JTree tree, TreePath path); /** * Returns the path to the element that is being edited. + * + * @param tree the {@code JTree} for which to return a path + * @return a {@code TreePath} containing the path to {@code tree} */ public abstract TreePath getEditingPath(JTree tree); } diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java index ffbd5ea628b..c7c5ad05a9d 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicInternalFrameUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 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 @@ -351,10 +351,15 @@ public class BasicInternalFrameUI extends InternalFrameUI /** - * Installs necessary mouse handlers on newPane - * and adds it to the frame. - * Reverse process for the currentPane. - */ + * Installs necessary mouse handlers on newPane + * and adds it to the frame. + * Reverse process for the currentPane. + * + * @param currentPane this {@code Jcomponent} is the current pane being + * viewed that has mouse handlers installed + * @param newPane this {@code Jcomponent} is the pane which will be added + * and have mouse handlers installed + */ protected void replacePane(JComponent currentPane, JComponent newPane) { if(currentPane != null) { deinstallMouseHandlers(currentPane); @@ -517,11 +522,12 @@ public class BasicInternalFrameUI extends InternalFrameUI } /// DesktopManager methods - /** Returns the proper DesktopManager. Calls getDesktopPane() to - * find the JDesktop component and returns the desktopManager from - * it. If this fails, it will return a default DesktopManager that - * should work in arbitrary parents. - */ + /** + * Returns the proper DesktopManager. Calls getDesktopPane() to + * find the JDesktop component and returns the desktopManager from + * it. If this fails, it will return a default DesktopManager that + * should work in arbitrary parents. + */ protected DesktopManager getDesktopManager() { if(frame.getDesktopPane() != null && frame.getDesktopPane().getDesktopManager() != null) @@ -539,6 +545,8 @@ public class BasicInternalFrameUI extends InternalFrameUI * This method is called when the user wants to close the frame. * The playCloseSound Action is fired. * This action is delegated to the desktopManager. + * + * @param f the {@code JInternalFrame} being viewed */ protected void closeFrame(JInternalFrame f) { // Internal Frame Auditory Cue Activation @@ -551,6 +559,8 @@ public class BasicInternalFrameUI extends InternalFrameUI * This method is called when the user wants to maximize the frame. * The playMaximizeSound Action is fired. * This action is delegated to the desktopManager. + * + * @param f the {@code JInternalFrame} being viewed */ protected void maximizeFrame(JInternalFrame f) { // Internal Frame Auditory Cue Activation @@ -563,6 +573,8 @@ public class BasicInternalFrameUI extends InternalFrameUI * This method is called when the user wants to minimize the frame. * The playRestoreDownSound Action is fired. * This action is delegated to the desktopManager. + * + * @param f the {@code JInternalFrame} being viewed */ protected void minimizeFrame(JInternalFrame f) { // Internal Frame Auditory Cue Activation @@ -579,6 +591,8 @@ public class BasicInternalFrameUI extends InternalFrameUI * This method is called when the user wants to iconify the frame. * The playMinimizeSound Action is fired. * This action is delegated to the desktopManager. + * + * @param f the {@code JInternalFrame} being viewed */ protected void iconifyFrame(JInternalFrame f) { // Internal Frame Auditory Cue Activation @@ -591,6 +605,8 @@ public class BasicInternalFrameUI extends InternalFrameUI * This method is called when the user wants to deiconify the frame. * The playRestoreUpSound Action is fired. * This action is delegated to the desktopManager. + * + * @param f the {@code JInternalFrame} being viewed */ protected void deiconifyFrame(JInternalFrame f) { // Internal Frame Auditory Cue Activation @@ -603,15 +619,21 @@ public class BasicInternalFrameUI extends InternalFrameUI getDesktopManager().deiconifyFrame(f); } - /** This method is called when the frame becomes selected. + /** + * This method is called when the frame becomes selected. * This action is delegated to the desktopManager. + * + * @param f the {@code JInternalFrame} being viewed */ protected void activateFrame(JInternalFrame f) { getDesktopManager().activateFrame(f); } - /** This method is called when the frame is no longer selected. - * This action is delegated to the desktopManager. - */ + /** + * This method is called when the frame is no longer selected. + * This action is delegated to the desktopManager. + * + * @param f the {@code JInternalFrame} being viewed + */ protected void deactivateFrame(JInternalFrame f) { getDesktopManager().deactivateFrame(f); } @@ -769,7 +791,7 @@ public class BasicInternalFrameUI extends InternalFrameUI resizeDir = SOUTH; } } else { - /* the mouse press happened inside the frame, not in the + /* the mouse press happened inside the frame, not in the border */ discardRelease = true; return; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java index c7642f4e4c4..ebb0862587a 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicScrollBarUI.java @@ -93,8 +93,10 @@ public class BasicScrollBarUI private final static int scrollSpeedThrottle = 60; // delay in milli seconds - /** True indicates a middle click will absolutely position the - * scrollbar. */ + /** + * True indicates a middle click will absolutely position the + * scrollbar. + */ private boolean supportsAbsolutePositioning; /** @@ -877,6 +879,10 @@ public class BasicScrollBarUI * Set the bounds of the thumb and force a repaint that includes * the old thumbBounds and the new one. * + * @param x set the x location of the thumb + * @param y set the y location of the thumb + * @param width set the width of the thumb + * @param height set the height of the thumb * @see #getThumbBounds */ protected void setThumbBounds(int x, int y, int width, int height) diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java index b6ca67de67e..433cb16b687 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicSliderUI.java @@ -397,13 +397,14 @@ public class BasicSliderUI extends SliderUI{ protected boolean labelsHaveSameBaselines() { if (!checkedLabelBaselines) { checkedLabelBaselines = true; - Dictionary dictionary = slider.getLabelTable(); + @SuppressWarnings("rawtypes") + Dictionary dictionary = slider.getLabelTable(); if (dictionary != null) { sameLabelBaselines = true; - Enumeration elements = dictionary.elements(); + Enumeration elements = dictionary.elements(); int baseline = -1; while (elements.hasMoreElements()) { - JComponent label = elements.nextElement(); + JComponent label = (JComponent) elements.nextElement(); Dimension pref = label.getPreferredSize(); int labelBaseline = label.getBaseline(pref.width, pref.height); @@ -656,10 +657,15 @@ public class BasicSliderUI extends SliderUI{ } /** - * Gets the height of the tick area for horizontal sliders and the width of the - * tick area for vertical sliders. BasicSliderUI uses the returned value to - * determine the tick area rectangle. If you want to give your ticks some room, - * make this larger than you need and paint your ticks away from the sides in paintTicks(). + * Gets the height of the tick area for horizontal sliders and the width of + * the tick area for vertical sliders. BasicSliderUI uses the returned value + * to determine the tick area rectangle. If you want to give your ticks some + * room, make this larger than you need and paint your ticks away from the + * sides in paintTicks(). + * + * @return an integer representing the height of the tick area for + * horizontal sliders, and the width of the tick area for the vertical + * sliders */ protected int getTickLength() { return 8; @@ -753,12 +759,13 @@ public class BasicSliderUI extends SliderUI{ } protected int getWidthOfWidestLabel() { - Dictionary dictionary = slider.getLabelTable(); + @SuppressWarnings("rawtypes") + Dictionary dictionary = slider.getLabelTable(); int widest = 0; if ( dictionary != null ) { Enumeration keys = dictionary.keys(); while ( keys.hasMoreElements() ) { - JComponent label = dictionary.get(keys.nextElement()); + JComponent label = (JComponent) dictionary.get(keys.nextElement()); widest = Math.max( label.getPreferredSize().width, widest ); } } @@ -766,12 +773,13 @@ public class BasicSliderUI extends SliderUI{ } protected int getHeightOfTallestLabel() { - Dictionary dictionary = slider.getLabelTable(); + @SuppressWarnings("rawtypes") + Dictionary dictionary = slider.getLabelTable(); int tallest = 0; if ( dictionary != null ) { Enumeration keys = dictionary.keys(); while ( keys.hasMoreElements() ) { - JComponent label = dictionary.get(keys.nextElement()); + JComponent label = (JComponent) dictionary.get(keys.nextElement()); tallest = Math.max( label.getPreferredSize().height, tallest ); } } @@ -842,18 +850,19 @@ public class BasicSliderUI extends SliderUI{ * @since 1.6 */ protected Integer getHighestValue() { - Dictionary dictionary = slider.getLabelTable(); + @SuppressWarnings("rawtypes") + Dictionary dictionary = slider.getLabelTable(); if (dictionary == null) { return null; } - Enumeration keys = dictionary.keys(); + Enumeration keys = dictionary.keys(); Integer max = null; while (keys.hasMoreElements()) { - Integer i = keys.nextElement(); + Integer i = (Integer) keys.nextElement(); if (max == null || i > max) { max = i; @@ -867,22 +876,23 @@ public class BasicSliderUI extends SliderUI{ * Returns the smallest value that has an entry in the label table. * * @return smallest value that has an entry in the label table, or - * null. + * null. * @since 1.6 */ protected Integer getLowestValue() { - Dictionary dictionary = slider.getLabelTable(); + @SuppressWarnings("rawtypes") + Dictionary dictionary = slider.getLabelTable(); if (dictionary == null) { return null; } - Enumeration keys = dictionary.keys(); + Enumeration keys = dictionary.keys(); Integer min = null; while (keys.hasMoreElements()) { - Integer i = keys.nextElement(); + Integer i = (Integer) keys.nextElement(); if (min == null || i < min) { min = i; @@ -894,7 +904,11 @@ public class BasicSliderUI extends SliderUI{ /** - * Returns the label that corresponds to the highest slider value in the label table. + * Returns the label that corresponds to the highest slider value in the + * label table. + * + * @return the label that corresponds to the highest slider value in the + * label table * @see JSlider#setLabelTable */ protected Component getLowestValueLabel() { @@ -906,7 +920,11 @@ public class BasicSliderUI extends SliderUI{ } /** - * Returns the label that corresponds to the lowest slider value in the label table. + * Returns the label that corresponds to the lowest slider value in the + * label table. + * + * @return the label that corresponds to the lowest slider value in the + * label table * @see JSlider#setLabelTable */ protected Component getHighestValueLabel() { @@ -1121,17 +1139,18 @@ public class BasicSliderUI extends SliderUI{ public void paintLabels( Graphics g ) { Rectangle labelBounds = labelRect; - Dictionary dictionary = slider.getLabelTable(); + @SuppressWarnings("rawtypes") + Dictionary dictionary = slider.getLabelTable(); if ( dictionary != null ) { - Enumeration keys = dictionary.keys(); + Enumeration keys = dictionary.keys(); int minValue = slider.getMinimum(); int maxValue = slider.getMaximum(); boolean enabled = slider.isEnabled(); while ( keys.hasMoreElements() ) { - Integer key = keys.nextElement(); + Integer key = (Integer)keys.nextElement(); int value = key.intValue(); if (value >= minValue && value <= maxValue) { - JComponent label = dictionary.get(key); + JComponent label = (JComponent) dictionary.get(key); label.setEnabled(enabled); if (label instanceof JLabel) { @@ -1166,8 +1185,14 @@ public class BasicSliderUI extends SliderUI{ } /** - * Called for every label in the label table. Used to draw the labels for horizontal sliders. - * The graphics have been translated to labelRect.y already. + * Called for every label in the label table. Used to draw the labels for + * horizontal sliders. The graphics have been translated to labelRect.y + * already. + * + * @param g the graphics context in which to paint + * @param value the value of the slider + * @param label the component label in the label table that needs to be + * painted * @see JSlider#setLabelTable */ protected void paintHorizontalLabel( Graphics g, int value, Component label ) { @@ -1179,8 +1204,14 @@ public class BasicSliderUI extends SliderUI{ } /** - * Called for every label in the label table. Used to draw the labels for vertical sliders. - * The graphics have been translated to labelRect.x already. + * Called for every label in the label table. Used to draw the labels for + * vertical sliders. The graphics have been translated to labelRect.x + * already. + * + * @param g the graphics context in which to paint + * @param value the value of the slider + * @param label the component label in the label table that needs to be + * painted * @see JSlider#setLabelTable */ protected void paintVerticalLabel( Graphics g, int value, Component label ) { @@ -1342,9 +1373,12 @@ public class BasicSliderUI extends SliderUI{ } /** - * This function is called when a mousePressed was detected in the track, not - * in the thumb. The default behavior is to scroll by block. You can - * override this method to stop it from scrolling or to add additional behavior. + * This function is called when a mousePressed was detected in the track, + * not in the thumb. The default behavior is to scroll by block. You can + * override this method to stop it from scrolling or to add additional + * behavior. + * + * @param dir the direction and number of blocks to scroll */ protected void scrollDueToClickInTrack( int dir ) { scrollByBlock( dir ); @@ -1387,6 +1421,7 @@ public class BasicSliderUI extends SliderUI{ * @param value the slider value to get the location for * @param trackY y-origin of the track * @param trackHeight the height of the track + * @return the y location for the specified value of the slider * @since 1.6 */ protected int yPositionForValue(int value, int trackY, int trackHeight) { @@ -1417,6 +1452,9 @@ public class BasicSliderUI extends SliderUI{ * track at the the bottom or the top, this method sets the value to either * the minimum or maximum value of the slider, depending on if the slider * is inverted or not. + * + * @param yPos the location of the slider along the y axis + * @return the value at the y position */ public int valueForYPosition( int yPos ) { int value; @@ -1449,6 +1487,9 @@ public class BasicSliderUI extends SliderUI{ * track at the left or the right, this method sets the value to either the * minimum or maximum value of the slider, depending on if the slider is * inverted or not. + * + * @param xPos the location of the slider along the x axis + * @return the value of the x position */ public int valueForXPosition( int xPos ) { int value; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java index bf27557ac99..7490b8ea458 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -1174,6 +1174,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { * this function draws the border around each tab * note that this function does now draw the background of the tab. * that is done elsewhere + * + * @param g the graphics context in which to paint + * @param tabPlacement the placement (left, right, bottom, top) of the tab + * @param tabIndex the index of the tab with respect to other tabs + * @param x the x coordinate of tab + * @param y the y coordinate of tab + * @param w the width of the tab + * @param h the height of the tab + * @param isSelected a {@code boolean} which determines whether or not + * the tab is selected */ protected void paintTabBorder(Graphics g, int tabPlacement, int tabIndex, @@ -3530,12 +3540,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { else if (name =="indexForTitle") { calculatedBaseline = false; Integer index = (Integer) e.getNewValue(); - // remove the current index - // to let updateHtmlViews() insert the correct one - if (htmlViews != null) { - htmlViews.removeElementAt(index); - } - updateHtmlViews(index); + updateHtmlViews(index, false); } else if (name == "tabLayoutPolicy") { BasicTabbedPaneUI.this.uninstallUI(pane); BasicTabbedPaneUI.this.installUI(pane); @@ -3574,13 +3579,13 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { calculatedBaseline = false; } else if (name == "indexForNullComponent") { isRunsDirty = true; - updateHtmlViews((Integer)e.getNewValue()); + updateHtmlViews((Integer)e.getNewValue(), true); } else if (name == "font") { calculatedBaseline = false; } } - private void updateHtmlViews(int index) { + private void updateHtmlViews(int index, boolean inserted) { String title = tabPane.getTitleAt(index); boolean isHTML = BasicHTML.isHTMLString(title); if (isHTML) { @@ -3588,16 +3593,24 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { htmlViews = createHTMLVector(); } else { // Vector already exists View v = BasicHTML.createHTMLView(tabPane, title); - htmlViews.insertElementAt(v, index); + setHtmlView(v, inserted, index); } } else { // Not HTML if (htmlViews!=null) { // Add placeholder - htmlViews.insertElementAt(null, index); + setHtmlView(null, inserted, index); } // else nada! } updateMnemonics(); } + private void setHtmlView(View v, boolean inserted, int index) { + if (inserted || index >= htmlViews.size()) { + htmlViews.insertElementAt(v, index); + } else { + htmlViews.setElementAt(v, index); + } + } + // // ChangeListener // @@ -3716,7 +3729,7 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { return; } isRunsDirty = true; - updateHtmlViews(tp.indexOfComponent(child)); + updateHtmlViews(tp.indexOfComponent(child), true); } public void componentRemoved(ContainerEvent e) { JTabbedPane tp = (JTabbedPane)e.getContainer(); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java index 0cc5b0ed831..2116e65a0f4 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthSliderUI.java @@ -269,7 +269,7 @@ public class SynthSliderUI extends BasicSliderUI centerY += valueHeight + 2; centerY += trackHeight + trackInsets.top + trackInsets.bottom; centerY += tickHeight + 2; - JComponent label = slider.getLabelTable().elements().nextElement(); + JComponent label = (JComponent) slider.getLabelTable().elements().nextElement(); Dimension pref = label.getPreferredSize(); return centerY + label.getBaseline(pref.width, pref.height); } @@ -291,7 +291,7 @@ public class SynthSliderUI extends BasicSliderUI int trackHeight = contentHeight - valueHeight; int yPosition = yPositionForValue(value.intValue(), trackY, trackHeight); - JComponent label = slider.getLabelTable().get(value); + JComponent label = (JComponent) slider.getLabelTable().get(value); Dimension pref = label.getPreferredSize(); return yPosition - pref.height / 2 + label.getBaseline(pref.width, pref.height); @@ -392,7 +392,8 @@ public class SynthSliderUI extends BasicSliderUI trackRect.x = insetCache.left; trackRect.width = contentRect.width; - Dictionary dictionary = slider.getLabelTable(); + @SuppressWarnings("rawtypes") + Dictionary dictionary = slider.getLabelTable(); if (dictionary != null) { int minValue = slider.getMinimum(); int maxValue = slider.getMaximum(); @@ -402,9 +403,9 @@ public class SynthSliderUI extends BasicSliderUI // slider range. int firstLblIdx = Integer.MAX_VALUE; int lastLblIdx = Integer.MIN_VALUE; - for (Enumeration keys = dictionary.keys(); + for (Enumeration keys = dictionary.keys(); keys.hasMoreElements(); ) { - int keyInt = keys.nextElement().intValue(); + int keyInt = ((Integer)keys.nextElement()).intValue(); if (keyInt >= minValue && keyInt < firstLblIdx) { firstLblIdx = keyInt; } @@ -517,7 +518,7 @@ public class SynthSliderUI extends BasicSliderUI private int getPadForLabel(int i) { int pad = 0; - JComponent c = slider.getLabelTable().get(i); + JComponent c = (JComponent) slider.getLabelTable().get(i); if (c != null) { int centerX = xPositionForValue(i); int cHalfWidth = c.getPreferredSize().width / 2; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/table/DefaultTableModel.java b/jdk/src/java.desktop/share/classes/javax/swing/table/DefaultTableModel.java index 4b9cc197575..2d34384693b 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/table/DefaultTableModel.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/table/DefaultTableModel.java @@ -70,10 +70,18 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * The Vector of Vectors of * Object values. */ - protected Vector> dataVector; + @SuppressWarnings("rawtypes") + protected Vector dataVector; /** The Vector of column identifiers. */ - protected Vector columnIdentifiers; + @SuppressWarnings("rawtypes") + protected Vector columnIdentifiers; + // Unfortunately, for greater source compatibility the inner-most + // Vector in the two fields above is being left raw. The Vector is + // read as well as written so using Vector is not suitable and + // using Vector (without adding copying of input Vectors), + // would disallow existing code that used, say, a Vector + // as an input parameter. // // Constructors @@ -121,7 +129,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * @see #setDataVector * @see #setValueAt */ - public DefaultTableModel(Vector columnNames, int rowCount) { + public DefaultTableModel(Vector columnNames, int rowCount) { setDataVector(newVector(rowCount), columnNames); } @@ -156,7 +164,8 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * @see #getDataVector * @see #setDataVector */ - public DefaultTableModel(Vector> data, Vector columnNames) { + @SuppressWarnings("rawtypes") + public DefaultTableModel(Vector data, Vector columnNames) { setDataVector(data, columnNames); } @@ -191,7 +200,8 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * @see #newRowsAdded * @see #setDataVector */ - public Vector> getDataVector() { + @SuppressWarnings("rawtypes") + public Vector getDataVector() { return dataVector; } @@ -219,9 +229,10 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * @param columnIdentifiers the names of the columns * @see #getDataVector */ - public void setDataVector(Vector> dataVector, - Vector columnIdentifiers) { - this.dataVector = nonNullVector(dataVector); + @SuppressWarnings({"rawtypes", "unchecked"}) + public void setDataVector(Vector dataVector, + Vector columnIdentifiers) { + this.dataVector = nonNullVector((Vector)dataVector); this.columnIdentifiers = nonNullVector(columnIdentifiers); justifyRows(0, getRowCount()); fireTableStructureChanged(); @@ -267,7 +278,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl if (dataVector.elementAt(i) == null) { dataVector.setElementAt(new Vector<>(), i); } - ((Vector)dataVector.elementAt(i)).setSize(getColumnCount()); + dataVector.elementAt(i).setSize(getColumnCount()); } } @@ -350,7 +361,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * * @param rowData optional data of the row being added */ - public void addRow(Vector rowData) { + public void addRow(Vector rowData) { insertRow(getRowCount(), rowData); } @@ -374,7 +385,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * @param rowData optional data of the row being added * @exception ArrayIndexOutOfBoundsException if the row was invalid */ - public void insertRow(int row, Vector rowData) { + public void insertRow(int row, Vector rowData) { dataVector.insertElementAt(rowData, row); justifyRows(row, row+1); fireTableRowsInserted(row, row); @@ -484,7 +495,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * to zero columns * @see #setNumRows */ - public void setColumnIdentifiers(Vector columnIdentifiers) { + public void setColumnIdentifiers(Vector columnIdentifiers) { setDataVector(dataVector, columnIdentifiers); } @@ -550,7 +561,8 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * @param columnName the identifier of the column being added * @param columnData optional data of the column being added */ - public void addColumn(Object columnName, Vector columnData) { + @SuppressWarnings("unchecked") // Adding element to raw columnIdentifiers + public void addColumn(Object columnName, Vector columnData) { columnIdentifiers.addElement(columnName); if (columnData != null) { int columnSize = columnData.size(); @@ -652,6 +664,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * column was given */ public Object getValueAt(int row, int column) { + @SuppressWarnings("unchecked") Vector rowVector = dataVector.elementAt(row); return rowVector.elementAt(column); } @@ -668,6 +681,7 @@ public class DefaultTableModel extends AbstractTableModel implements Serializabl * column was given */ public void setValueAt(Object aValue, int row, int column) { + @SuppressWarnings("unchecked") Vector rowVector = dataVector.elementAt(row); rowVector.setElementAt(aValue, column); fireTableCellUpdated(row, column); diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java b/jdk/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java index 111ab923a85..6b1bf61bb00 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/AbstractDocument.java @@ -1426,11 +1426,18 @@ public abstract class AbstractDocument implements Document, Serializable { // --- serialization --------------------------------------------- + @SuppressWarnings("unchecked") private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { - s.defaultReadObject(); + ObjectInputStream.GetField f = s.readFields(); + + documentProperties = + (Dictionary) f.get("documentProperties", null); listenerList = new EventListenerList(); + data = (Content) f.get("data", null); + context = (AttributeContext) f.get("context", null); + documentFilter = (DocumentFilter) f.get("documentFilter", null); // Restore bidi structure //REMIND(bcb) This creates an initial bidi element to account for diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java b/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java index 5eb0b2b10fe..cd17fed60bd 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultCaret.java @@ -1516,7 +1516,30 @@ public class DefaultCaret extends Rectangle implements Caret, FocusListener, Mou private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { - s.defaultReadObject(); + ObjectInputStream.GetField f = s.readFields(); + + EventListenerList newListenerList = (EventListenerList) f.get("listenerList", null); + if (newListenerList == null) { + throw new InvalidObjectException("Null listenerList"); + } + listenerList = newListenerList; + component = (JTextComponent) f.get("component", null); + updatePolicy = f.get("updatePolicy", 0); + visible = f.get("visible", false); + active = f.get("active", false); + dot = f.get("dot", 0); + mark = f.get("mark", 0); + selectionTag = f.get("selectionTag", null); + selectionVisible = f.get("selectionVisible", false); + flasher = (Timer) f.get("flasher", null); + magicCaretPosition = (Point) f.get("magicCaretPosition", null); + dotLTR = f.get("dotLTR", false); + markLTR = f.get("markLTR", false); + ownsSelection = f.get("ownsSelection", false); + forceCaretPositionChange = f.get("forceCaretPositionChange", false); + caretWidth = f.get("caretWidth", 0); + aspectRatio = f.get("aspectRatio", 0.0f); + handler = new Handler(); if (!s.readBoolean()) { dotBias = Position.Bias.Forward; diff --git a/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java b/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java index 78788cbfad1..09faa5671cb 100644 --- a/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java +++ b/jdk/src/java.desktop/share/classes/javax/swing/text/DefaultStyledDocument.java @@ -1082,8 +1082,9 @@ public class DefaultStyledDocument extends AbstractDocument implements StyledDoc private void readObject(ObjectInputStream s) throws ClassNotFoundException, IOException { - listeningStyles = new Vector

    Audio System Property Keys